为什么\ B工作但不是\ b

时间:2013-05-18 10:22:56

标签: java javascript .net regex

想要匹配以<{1}}结尾的

你好你好# 世界#

我试图使用边界

#

并且它不匹配。我认为\b\w+#\b 是一个非单词边界但是从这种情况看起来并非如此


令人惊讶

\b

匹配!

那么为什么\b\w+#\B 在这里工作而不是\B!为什么\b在这种情况下不起作用!


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

3 个答案:

答案 0 :(得分:6)

单词边界\b

的定义

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

单词边界\b相当于:

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

这意味着:

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

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

(注意这与XOR扩展为连接和分离有多相似)

非字边界\B相当于:

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

这意味着:

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

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

(注意这与XNOR扩展为连接和分离有多相似)。

单词字符\w

的定义

由于\b\B的定义取决于\w 1 的定义,因此您需要查阅具体文档以确切了解{{1}匹配。

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

回答问题

根据上面的定义,回答问题变得容易:

[\p{Ll}\p{Lu}\p{Lt}\p{Lo}\P{Lm}\p{Nd}\p{Pc}]

"hi hello# world#" 中,hello#为空格(U+0020, in Zs category)后,这不是单词字符,而#不是单词字符本身({{3} })。因此,#可以在这里匹配。在这种情况下使用分支\B

(?<!\w)(?!\w)中,world#结束字符串后。由于#不是单词字符,并且我们无法找到前面的任何单词字符(没有任何内容),#可以匹配\B之后的空字符串。在这种情况下也使用分支#

附录

艾伦·摩尔在in Unicode, it is in Po category中给出了相当不错的总结:

  

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

答案 1 :(得分: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

答案 2 :(得分:1)

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