Why doesn't C# RegEx class respect Environment.NewLine?

Viewed 129

I'm using C# interactive, and here is the setup:

#r "System.Text.RegularExpressions"
using System.Text.RegularExpressions;
string s = "Number 42" + Environment.NewLine + "and 1 number 3";

I'm looking to add brackets around all numbers at the end of a line, or at end of string (42 and 3 should both get brackets).

Note: on my system Environment.NewLine is \r\n

So I try Regex.Replace(s, "(\\d+)$", "[$0]", RegexOptions.Multiline) and only the 3 gets wrapped.

If I do Regex.Replace(s, "(\\d+)\r?$", "[$0]", RegexOptions.Multiline) both get wrapped but one has an extra \r inside the brackets. So the regex engine is believing the lie that Environment.NewLine is \n.

Is there a separate Environment.NewLine setting just for regexes? If so, how do I set it?

1 Answers

The $ anchor is a regex construct. The Environment.NewLine ("\r\n for non-Unix platforms, or \n for Unix platforms") is not referred to from within the regex library and is a separate property.

You can use

Regex.Replace(s, @"\d+(?=\r?$)", "[$&]", RegexOptions.Multiline)

See the regex demo:

enter image description here

Details

  • \d+ - 1+ digits
  • (?=\r?$) - followed with an optional CR then followed with the end of the line.

The point is that when you use RegexOptions.Multiline the $ anchor matches a location right before the LF (\n) symbol. There is no way to redefine this behavior. The Environment.NewLine in Windows inserts CRLF line ending sequence, so you get \r\n as line endings. So, adding \r? before $ is a valid way to match end of line positions.

Related