Regex 带破折号的正则表达式问题

Regex 带破折号的正则表达式问题,regex,Regex,我对正则表达式有一些问题。 我正在测试案例1 \b(water|watering)\b/g 以上表达式可以成功匹配“water watering” 但是如果我在案例2的中间添加了一个连字符: \b(water|water-ing)\b/g 它无法与“water-water-ing”中的“water-water-ing”匹配 仅当我将“water-ing”表达式移到前面时,它才起作用,如案例3所示: \b(water-ing|water)\b/g 但我想知道,在不改变捕获组顺序的情况下,是否

我对正则表达式有一些问题。 我正在测试案例1

\b(water|watering)\b/g
以上表达式可以成功匹配“water watering”

但是如果我在案例2的中间添加了一个连字符:

\b(water|water-ing)\b/g
它无法与“water-water-ing”中的“water-water-ing”匹配
仅当我将“water-ing”表达式移到前面时,它才起作用,如案例3所示:

\b(water-ing|water)\b/g
但我想知道,在不改变捕获组顺序的情况下,是否有任何解决方案

以下是参考资料:

您可以这样做:

\b(water-ing|water)\b/g
\b(water(?:-ing)?)\b/g

因为“water”在“water-ing”中,你必须把“water-ing”放在第一位,如果正则表达式找不到它,它就会尝试找到“water”

或者您可以这样做:

\b(water-ing|water)\b/g
\b(water(?:-ing)?)\b/g
必须使用“?:”以避免创建另一个带有“()”的组


不同的正则表达式引擎为“单词边界”定义不同的字符集。例如,
-
未在此处列出。因此,
-
在ECMAScript中被视为单词边界

显然,
\b
不适合Unicode单词。所以你应该使用你自己的一组字符,它们应该是单词的边界

例如,在PHP中,您可以使用以下内容:

preg_match_all('/[\p{L}-]+/u','water-water-ing',$m);
var_dump(百万美元);
/*
阵列(1){
[0]=>
阵列(2){
[0]=>
串(5)“水”
[1]=>
第(9)串“注水”
}
}
*/
其中,
\p{L}
代表一个。请参见

您可以使用:
\b(水)水?)\g
关于交替的注意事项

在替换中,在字符串中的当前位置检查每个替换,直到其中一个替换成功或全部失败

案例一

你的绳子是

water watering
water water-ing
你的正则表达式是

/\b(water|watering)\b/g
i) 首先,像
\bwater
一样检查第一次交替。它成功并匹配了
water
,因为
water watering
中的water之后有一个空格作为结束词边界

ii)由于
g
标志,再次执行匹配。因此,字符串
watering
正在尝试与
\bwater\b
(以及结尾的单词边界)匹配,但它失败了,因为
water
之后watering中存在
i
,这不是单词边界。然后检查第二个替换,即
\bwatering
,它成功了,因为在最后一个替换中,字符串的末尾充当
\bwatering\b
的单词边界

案例二

你的绳子是

water watering
water water-ing
正则表达式

/\b(water|water-ing)\b/g
/\b(water-ing|water)\b/g
i) 与案例一的步骤一相同

现在绳子到水被消耗了,我们的检查位置是浇水前的空白

water water-ing
    ^^
    || 
ii)由于
g
标志再次执行检查。使用
\b水
尝试第一次交替。现在的位置是
-
就在
r
之后和
i
之前

water water-ing
          ^^
          || 
引用关于单词边界

在大多数regex方言中,单词边界位于\w和\n之间 \W(非单词字符),或在字符串的开头或结尾,如果 分别以单词字符([0-9A-Za-z_])开始或结束。 破折号不是单词字符

因此,
-
充当单词边界,
\bwater\b
water-ing

案例三

正则表达式

/\b(water|water-ing)\b/g
/\b(water-ing|water)\b/g
i) 在字符串中选中了第一个替换项
\b水
,但它与字符串
不匹配。再次检查第二次交替
\bwater
,它成功了,因为字符串中
water
后面有一个空格

ii)在出现的字符串中检查第一次交替
\b注水
。字符串以单词
water-ing
结尾。所以字符串的结尾(
$
)充当单词边界。比赛成功了

解决方案是什么?

i) 如果存在重叠的正则表达式,请在开始时保留最长的正则表达式,依此类推,就像在上一个解决方案中使用的一样

ii)您可以使用负前瞻,如

\b(water(?!-)|water-ing)\b

它似乎已经提出了四个解决方案。您可以使用它们中的任何一个

发生这种情况是因为
中的
-
和单词边界
\b
。如果不重新排序或更改第一个分支模式,您将无法实现您想要的目标。我的意思是:1)或,或2)。