我有以下文字:
“猫狗老鼠狮子”
我使用正则表达式搜索“狗”或“鼠标”:
Regex regex = new Regex(@"dog|mouse");
C# 中正则表达式的行为方式是它首先搜索单词 dog。如果找到匹配项,它将停止。在正则表达式中找到我的任何单词第一次出现后,如何让它停止,这意味着在“cat”之后停止,因为这首先出现?
我是否必须进行多次正则表达式搜索并匹配结果的索引?或者是否可以在正则表达式中指定它?
不,你错了。
Regex regex = new Regex(@"dog|mouse");
和
Regex regex = new Regex(@"mouse|dog");
两者都会找到“狗”这个词,即使在第二种情况下,“鼠标”这个词是交替中的第一个。
匹配行为与您描述的不同。正则表达式将检查第一个字符是否可以匹配第一个选项,如果不匹配,它将不会继续到第二个字符,它将尝试第二个选项。
但是,交替的顺序在另一方面很重要。当您有相同开头的替代品并且您从短到长订购它们时,您会遇到问题,例如
Regex regex = new Regex(@"Foo|Foobar");
这永远不会匹配单词“Foobar”,因为即使文本中有 Foobar,它也会匹配第一个替代词“Foo”。
为避免这些问题,请从长到短排序
Regex regex = new Regex(@"Foobar|Foo");
这将尝试匹配“Foo”上的“Foobar”,当它识别出之后没有“b”时,它会尝试第二种选择并成功匹配“Foo”。
一种方法是使用带有 dotall 选项的惰性量词:
Regex regex = new Regex(@"^.*?\b(?>dog|mouse)\b");
另一种方法是这样做;
Regex regex = new Regex(@"^(?>[^dm]*+|d++(?!og\b)|m++(?!ouse\b))*\b(?>dog|mouse)\b");
它更长但更有效。这个想法是避免延迟量词很慢,因为它会测试每个字符以查看后面的内容。在这里,我将开头描述为“所有不是 ad
或m
OR 的东西,一些d
不跟og
OR 一些m
不跟ouse
零次或多次。
(?>..)
是一个原子组,这是为了避免正则表达式引擎回溯,它是一种“全有或全无”,更多信息在这里
++
是一个所有格量词,也可以避免回溯。