正则表达式的“ ^”和“ $”,see the documentation:
^
默认情况下,匹配必须从字符串的开头开始;在多行模式下,它必须从行的开头开始。
和
$
默认情况下,匹配必须发生在字符串末尾或\ n之前。在多行模式下,它必须发生在行尾之前或行尾\ n之前。
这样,我希望当我们指定没有 RegexOptions 参数的 Regex(pattern)时,会产生与 Regex(pattern, RegexOptions.Singleline)。
鉴于上述情况,任何人都可以解释以下代码的结果:
var text = $"{Environment.NewLine}a{Environment.NewLine}b";
var patN = @"^.*$";
var reN = new Regex(patN);
var msN = reN.Matches(text);
Console.WriteLine($"Begin and end specified: {msN.Count}");
Console.WriteLine();
var patB = @"^.*";
var reB = new Regex(patB);
var msB = reB.Matches(text);
foreach (var mB in msB)
Console.WriteLine($"Begin specified only : {string.Join(" ", mB.ToString().Select(c => (int)c))}");
Console.WriteLine();
var patE = @".*$";
var reE = new Regex(patE);
var msE = reE.Matches(text);
foreach (var mE in msE)
Console.WriteLine($"End specified only : {string.Join(" ", mE.ToString().Select(c => (int)c))}");
结果:
Begin and end specified: 0
Begin specified only : 13
End specified only : 98
End specified only :
字符98为“ b”
答案 0 :(得分:3)
摘自Regex constructor的文档:
调用Regex(String)构造函数等效于为options参数调用值为None的Regex(String,RegexOptions)构造函数。
因此,您对默认行为是SingleLine的期望是错误的。
如Default options中所述:
^
和$
语言元素与输入字符串的开头和结尾匹配。
第一个示例返回零,因为...来自Quick language reference
.
通配符:匹配\ n以外的任何单个字符。
答案 1 :(得分:1)
问题的第一部分只是对正则表达式标志m | multiline和s | singleline的常见误解。由于这对于几乎所有正则表达式而言都是很常见的,因此我想引用perlretut:
(我将\n
替换为newline
(稍后再说)和其他小调整)
当我们计算和匹配字符时,我们通常希望忽略换行符 排成一行。但是,有时我们想跟踪换行符。我们 甚至可能希望
^
和$
锚定在 字符串中的行,而不仅仅是行的开头和结尾 串。 [实现这些修改的大多数正则表达式引擎允许] 在忽略和关注换行之间选择,方法是使用s
和m
修饰符。s
和m
代表单行, 多行,并确定是否将一个字符串视为一个 连续的字符串或一组线。这两个修饰符会影响两个 regexp的解释方式:
.
字符如何 类已定义,并且- 锚点
^
和$
能够匹配的地方。以下是四种可能的组合:
- 无修饰符:默认行为。
.
与newline
以外的任何字符匹配。^
仅匹配字符串的开头,$
仅匹配字符串 在末尾或在换行符之前。- s修饰符
(?s)
:将字符串视为单个长行。.
匹配任何字符,甚至newline
。^
仅在开始时匹配 字符串和$仅在末尾或在换行符末尾匹配。- m修饰符
(?m)
:将字符串视为一组多行。.
与newline
以外的任何字符匹配。^
和$
能够在 字符串中任何行的开头或结尾。- s和m修饰符
(?sm)
:将字符串视为单个长行,但检测到多行。.
匹配任何字符,甚至newline
。^
和$
,但是可以在任何行的开头或结尾进行匹配 在字符串中。
由于新的Regex(String)的constructor没有添加任何RegexOptions,因此您肯定处于第一种情况,如前所述。
现在输出。这里的问题是:正则表达式引擎的换行符是什么?如果是Windows或其他操作系统,这是否取决于您的环境(如代码所建议)? .NET documentation on anchors很清楚:regex中的换行符是:\n
引用End of String or Line: $中的一段内容:
如果将
$
与RegexOptions.Multiline选项一起使用,则匹配项可以 也发生在行尾。请注意,$
与\n
匹配,但与 不匹配\r\n
(回车符和换行符或CR / LF的组合)。要匹配CR / LF字符组合, 在正则表达式模式中包含\r?$
。 (已添加突出显示)
因此,由于示例代码将Windows环境中的输入文本定义为:\r\na\r\nb
,这说明了您的输出:^.*
与字符串第一行中的\r
相匹配。如果您在Linux环境上运行相同的代码,则不会得到匹配:Sample。
运行b
的{{1}}的匹配现在应该很明显。以下空匹配可能会令人惊讶。但是,由于.*$
匹配零个或多个字符,并且.NET regex .*
方法的行为类似于全局,因此可以在Matches()
之后的位置再次匹配。
奖金:
如果使用b
,则以
字符串仍然可以与(?m)
(start of the string only)匹配,并且字符串的末尾仍可以与锚点\A
(matches both the end and
the newline before, like $
)和{{1} }(matches only the end of the string)。