为什么以下正则表达式不匹配连字符(或者&符号,句号或逗号,虽然我暂时将它们从下面的字符类中排除)?我试图匹配像......这样的字符串。
h eh - l ow 1
...(这是单词" hello"的语音表示)并且当字符串中有连字符时匹配失败(对于&符号,上面列出的符号相同)。 / p>
Regex.Match(SomeText, "^(\b(?:aa|ae|ah|ao|aw|ax|ay|b|ch|d|dh|eh|er|ey|f|g|h|ih|iy|jh|k|l|m|n|ng|ow|oy|p|r|s|sh|t|th|uh|uw|v|w|y|z|zh|[12\-])\b ?)+$", RegexOptions.IgnoreCase).Success
这种模式......
^(\b(?:a|b|-)\b ?)+$
...根据regex101.com的说法,它基本上是完全相同的模式,所以我不明白为什么较长的一个不工作。
答案 0 :(得分:1)
您对错误的词边界的理解。但不要感到难过,这是最容易被误解的正则表达式构造之一。你需要知道,正如我们定义的那样,正则表达式引擎并不知道单词是什么。对它来说,一个单词只是一个或多个单词字符的序列(即由\w
匹配的字符。)
但无论如何你定义它们,正则表达式并不能真正匹配单词。它只能永远地看到"任何给定时间的两个字符:下一个和前一个字符。 \b
匹配的位置是一个后跟一个单词字符而不是一个单词的位置(可能是一个单词的开头),或者前面是一个单词字符而不是一个单词字符(可能是一句话的结尾)。
你可以通过像zx81 did这样的战略分组来使你的正则表达式工作,但你最好摆脱单词边界。他们的目的是确保你匹配的词不是更长词的一部分。你不需要它们,因为从上下文中已经清楚了:每个单词都是(1)前面是空格或字符串的开头,(2)后跟一个空格或结尾字符串。
"(?in)^((aa|ae|ah|ao|aw|ax|ay|b|ch|d|dh|eh|er|ey|f|g|h|ih|iy|jh|k|l|m|n|ng|ow|oy|p|r|s|sh|t|th|uh|uw|v|w|y|z|zh|[12]|-)( |$))+$"
如果您想知道,n
中的(?in)
会启用ExplicitCapture模式,这会使群组无法捕获。 (ref)
答案 1 :(得分:0)
因为单词边界\b
在单个连字符-
的任一侧无法匹配。我们需要将边界移动到它们仅围绕文本或数字的位置。
这将有效:
^(?:\b(?:aa|ae|ah|ao|aw|ax|ay|b|ch|d|dh|eh|er|ey|f|g|h|ih|iy|jh|k|l|m|n|ng|ow|oy|p|r|s|sh|t|th|uh|uw|v|w|y|z|zh|[12])\b|[ -])+$
请参阅 the regex demo 。
请注意,在VB.NET中,如果使用自由间距模式,这将更容易阅读:
Dim RegexObj As New Regex( _
"^ # start of string" & chr(10) & _
"(?: # non-capture group" & chr(10) & _
" \b # word boundary" & chr(10) & _
" (?: # non-capture group" & chr(10) & _
" aa|ae|ah|ao|aw|ax|ay|b|ch|d|dh|eh|" & chr(10) & _
" er|ey|f|g|h|ih|iy|jh|k|l|m|n|ng|ow|" & chr(10) & _
" oy|p|r|s|sh|t|th|uh|uw|v|w|y|z|zh" & chr(10) & _
" ) # end group" & chr(10) & _
" \b # word boundary" & chr(10) & _
" | # OR" & chr(10) & _
" [ 12-] # one of these characters" & chr(10) & _
")+ # repeat" & chr(10) & _
"$ # end of string", _
RegexOptions.IgnorePatternWhitespace)
另外,只是为了好玩,请注意长字母的交替可以缩短为
aa|er|ng|[ac-eijs-uz]h|[aou]w|[aeio]y|a[eox]|[bdf-hk-npr-tvwyz]