【问题标题】:why does \B works but not \b为什么 \B 有效但 \b 无效
【发布时间】:2013-05-13 10:57:11
【问题描述】:

想要匹配一个以# 结尾的单词,比如

你好 hello# world#

我尝试使用边界

\b\w+#\b

它不匹配。我认为\b 是一个非单词边界,但从这种情况下似乎不是这样


出乎意料

\b\w+#\B

匹配!

那么为什么\B 在这里有效,而\b 无效!还有为什么\b 在这种情况下无效!


注意: 是的,我们可以使用\b\w+#(?=\s|$),但我想知道为什么\B 在这种情况下有效!

【问题讨论】:

  • @Anirudh 我认为这是因为第一个 # 之后的空间。
  • @MarounMaroun 确实是的,并且该空间应该与\b匹配
  • 它与空间无关...与#有关。
  • @AymanSafadi 它确实与空格有关,因为模式确实匹配字符串hi hello#world#

标签: java javascript .net regex


【解决方案1】:

字边界的定义\b

在单词中定义单词边界是不精确的。让我用look-aheadlook-behind和简写字字符类\w来定义字边界。

一个字边界\b 等价于:

(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))

这意味着:

  • 在前面,(至少)有一个字符是单词字符,并且在后面,我们找不到单词字符(该字符不是单词字符,或者是字符串的开头)。

  • 在后面,(至少)有一个字符是单词字符,并且在前面,我们找不到单词字符(该字符不是单词字符,或者是字符串的结尾)。

(注意这与 XOR 扩展为合取和析取有多么相似)

非单词边界\B 等价于:

(?:(?<!\w)(?!\w)|(?<=\w)(?=\w))

这意味着:

  • 在前面和后面,我们找不到任何单词字符。请注意,在此定义下,空字符串被视为非单词边界。

  • 前后左右,两边都是字。请注意,此分支需要 2 个字符,即不能出现在非空字符串的开头或结尾。

(注意这与将 XNOR 扩展为合取和析取有多么相似)。

字字符的定义\w

由于\b\B的定义依赖于\w的定义1,你需要查阅具体的文档才能知道\w到底匹配什么。

1 大多数正则表达式风格基于\w 定义\b。好吧,except for Java [Point 9],在默认模式下,\w 仅支持 ASCII,\b 部分支持 Unicode。

回答问题

有了上面的定义,回答问题就变得容易了:

"hi hello# world#"

hello# 中,# 之后是空格 (U+0020, in Zs category),它不是单词字符,# 本身不是单词字符 (in Unicode, it is in Po category)。因此,\B 可以在这里匹配。在这种情况下使用分支(?&lt;!\w)(?!\w)

world# 中,# 之后是字符串的结尾。由于# 不是单词字符,而且我们在前面找不到任何单词字符(那里什么都没有),所以\B 可以匹配# 之后的空字符串。在这种情况下也使用了分支(?&lt;!\w)(?!\w)

附录

Alan Moore 在the comment 中给出了很好的总结:

我认为要记住的关键点是正则表达式无法读取。也就是说,它们不处理文字,只处理字符。当我们说\b 匹配一个单词的开头或结尾时,我们并不是说它会识别一个单词,然后像人类那样寻找它的端点。它所能看到的只是字符 before 当前位置和字符 after 当前位置。因此,\b 仅表示当前位置可能是单词边界。由你来确定两边的角色应该是什么。

【讨论】:

  • 我认为要记住的关键点是正则表达式无法读取。也就是说,它们不处理文字,只处理字符。当我们说\b 匹配一个词的开头或结尾时,我们并不是说它会识别一个词,然后像人类那样寻找它的端点。它所能看到的只是当前位置之前的字符和当前位置之后的字符。因此,\b 仅表示当前位置可能是一个单词边界。由你来确定两边的字符应该是什么。
【解决方案2】:

# 和空格都是非单词字符,所以它们之间的不可见边界不是单词边界。因此\b 不会匹配它,\B 会匹配它。

【讨论】:

    【解决方案3】:

    英镑# 符号不被视为“单词边界”。

    \b\w+#\b 不起作用,因为 w+# 不被视为一个词,因此它不会匹配 world#
    另一方面,\b\w+6\b 是,因此它 匹配world6

    “单词字符”定义为:[A-Za-z0-9_]

    简单地说:\b 允许您使用\bword\b 形式的正则表达式执行“仅整个单词”搜索。 “单词字符”是可用于构成单词的字符。所有不是“单词字符”的字符都是“非单词字符”。

    ——http://www.regular-expressions.info/wordboundaries.html

    【讨论】:

    • 确实是的..但是\b.+?\b 似乎也匹配任何包含非单词字符的单词
    • 所以\b 不是正则表达式匹配的字符,它是anchor。换句话说,您的 RegEx 不匹配单词或非单词字符,它在您的第一个示例中匹配 w+#,在您的第二个示例中匹配 .+?(任何内容)。您正在使用 \b 锚来描述比赛的“环境”。
    • The pound # symbol is not considered a "word boundary". 单词边界不是由单个字符定义的。它由 2 个字符定义。 "Word Characters" are defined by: [A-Za-z0-9_]. 取决于您使用的语言。如果我们谈论的是 .NET,那么它将包含 Unicode 字符。
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 2022-01-12
    • 2020-05-14
    • 2020-10-07
    相关资源
    最近更新 更多