1

想要匹配以like结尾的单词#

你好你好# 世界#

我尝试使用边界

\b\w+#\b

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


出奇

\b\w+#\B

火柴!

那么为什么在\B这里有效而不是\b!为什么\b在这种情况下不起作用!


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

4

3 回答 3

6

词界的定义\b

在单词中定义单词边界是不精确的。让我用look-aheadlook-behind和short-hand word character class来定义单词边界\w

单词边界\b等价于:

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

意思是:

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

    或者

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

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

非单词边界\B等价于:

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

意思是:

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

    或者

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

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

字字的定义\w

由于\band的定义\B取决于\w1的定义,因此您需要查阅特定文档以确切了解\w匹配的内容。

1大多数正则表达式风格\b基于\w. 好吧,除了 Java [Point 9]之外,在默认模式下,\w它只支持 ASCII,并且\b部分支持 Unicode。

  • JavaScript中,它将[A-Za-z0-9_]处于默认模式。

  • .NET中,\w默认情况下会 match ,如果指定了ECMAScript 选项[\p{Ll}\p{Lu}\p{Lt}\p{Lo}\P{Lm}\p{Nd}\p{Pc}],它将具有与 JavaScript 相同的行为。在Pc 类别的字符列表中,您只需知道不包括空格(ASCII 32)。

回答问题

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

"hi hello# world#"

hello#,后面#是空格(U+0020,Zs类),不是单词字符,#本身也不是单词字符(Unicode中是Po类)。因此,\B可以在这里匹配。(?<!\w)(?!\w)在这种情况下使用分支。

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

附录

Alan Moore 在评论中给出了很好的总结:

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

于 2013-05-18T12:59:52.987 回答
5

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

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

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

简单地说:\b允许您使用\bword\b. “单词字符”是可用于构成单词的字符。所有不是“单词字符”的字符都是“非单词字符”。

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

于 2013-05-18T10:43:32.660 回答
1

#空格都是非单词字符,所以它们之间的隐形边界不是单词边界。因此\b将不匹配它\B并将匹配它。

于 2013-05-18T10:47:38.497 回答