正则表达式不匹配连字符和其他标点符号

时间:2014-07-25 23:50:15

标签: regex vb.net

为什么以下正则表达式不匹配连字符(或者&符号,句号或逗号,虽然我暂时将它们从下面的字符类中排除)?我试图匹配像......这样的字符串。

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的说法,它基本上是完全相同的模式,所以我不明白为什么较长的一个不工作。

2 个答案:

答案 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]