我在使用正则表达式时遇到了一些问题。 我正在测试机智案例1
\b(water|watering)\b/g
以上表达式可以匹配"浇水"成功。
但如果我在案例2之间加了一个连字符:
\b(water|water-ing)\b/g
它不能与水中的浇水相匹配"。
它只适用于我移动"浇水"表达到前面,如案例3:
\b(water-ing|water)\b/g
但我想知道案例编号2是否有任何解决方案,而不修改捕获组的顺序。
答案 0 :(得分:2)
你可以这样做:
\b(water-ing|water)\b/g
https://regex101.com/r/fC8wO1/1
因为“水”在“浇水”里面,你必须首先“浇水”,如果正则表达不能找到它,它会试图找到“水”。
或者你可以这样做:
\b(water(?:-ing)?)\b/g
使用“?:”来避免使用“()”创建另一个组非常重要。
答案 1 :(得分:2)
关于轮替的注意事项
在交替中,在字符串中的当前位置检查每个替代项,直到其中一个交替成功或全部失败。
案例I
你的字符串是
water watering
你的正则表达式是
/\b(water|watering)\b/g
i)首先,检查第一次交替,如\bwater
。它成功并且water
匹配,因为water watering
中的水后面有一个空格作为结束词边界。
ii)再次由于g
标志,执行匹配。因此,正在尝试将字符串watering
与\bwater\b
(以及最后的字边界)匹配,但它失败了,因为在i
后water
中有\bwatering
这不是字边界。然后检查第二次交替,即\bwatering\b
并且它成功,因为最后有一个字符串结尾作为water water-ing
的字边界。
案例II
你的字符串是
/\b(water|water-ing)\b/g
正则表达式
water water-ing
^^
||
i)与案例I的第I步相同
现在消耗了水,我们的检查位置是空白空间,然后浇水
g
ii)再次由于\bwater
标志执行检查。首先使用-
进行替换。该位置现在位于r
之后i
water water-ing
^^
||
-
引自 here 关于字边界
大多数正则表达式方言中的单词边界是\ w和。之间的位置 \ W(非单词char),或者如果是字符串的开头或结尾 用字符([0-9A-Za-z_])开始或结束(分别)。 破折号不是单词字符。
因此\bwater\b
充当单词边界,water-ing
/\b(water-ing|water)\b/g
案例III
正则表达式
\bwater-ing
i)首先在字符串中检查water
,但它与字符串\bwater
不匹配。再次,检查第二个替换water
并且成功,因为字符串中\bwater-ing
之后有一个空格。
ii)在存在的字符串中检查第一次交替water-ing
。该字符串以此单词$
结尾。所以字符串的结尾(\b(water(?!-)|water-ing)\b
)充当单词边界。并且匹配成功。
解决方案是什么?
i)如果正则表达式重叠,请保留最长的正则表达式,依此类推,就像在上一个解决方案中使用的一样
ii)你可以使用像
这样的负向前瞻--r--r--r--o--o--o (src)
|
(origin/dst)
git push +src:dst
--r--r--r--o--o--o (src)
|
(origin/dst)
似乎Wiktor已经提出了四种解决方案。你可以使用其中任何一个
答案 2 :(得分:0)
不同的正则表达式引擎为“单词边界”定义不同的字符集。例如,ECMAScript specifies a word character as one of 63 characters和-
未列在那里。因此-
被视为ECMAScript中的单词边界。
显然,\b
不适合Unicode字。所以你应该使用你自己的一组字符,这些字符应该是字边界。
例如,在PHP中,您可以使用以下内容:
preg_match_all('/[\p{L}\-]+/u', 'water water-ing', $m);
var_dump($m);
/*
array(1) {
[0]=>
array(2) {
[0]=>
string(5) "water"
[1]=>
string(9) "water-ing"
}
}
*/
其中\p{L}
代表Unicode "letter" category。见PHP Unicode character properties
答案 3 :(得分:0)
你可以用这个:
\b(water(ing)?)\g