Emacs正则表达式:\<和\>相比\b有什么优势?

12

Regexp Backslash - GNU Emacs Manual指出,\<匹配单词的开头,\>匹配单词的结尾,而\b则匹配单词边界。与其他非Emacs正则表达式一样,\b也是相同的。但似乎\<\>只适用于Emacs正则表达式。是否存在需要使用\<\>而不是\b的情况?例如,\bword\b\<word\>将匹配相同的内容,唯一的区别在于后者更易读。


它们也存在于GNU Grep和Vim中。 - Josh Lee
3
\<\> 来自原始的 vi,并且一直沿用至今。 - tchrist
2个回答

15

如果您假设它们的行为相同,可能会得到意想不到的结果。..
那么\<\>可以做什么呢?
答案是,\<\>显式的...只匹配单词结尾!而且只能匹配单词结尾!
\b通用的...可以匹配单词的任何一端...

GNU 运算符 * 单词运算符

line="cat dog sky"  
echo "$line" |sed -n "s/\(.*\)\b\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\>\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\<\(.*\)/# |\1|\2|/p"
echo
line="cat  dog  sky"  
echo "$line" |sed -n "s/\(.*\)\b\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\>\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\<\(.*\)/# |\1|\2|/p"
echo
line="cat  dog  sky  "  
echo "$line" |sed -n "s/\(.*\)\b\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\>\(.*\)/# |\1|\2|/p"
echo "$line" |sed -n "s/\(.*\)\<\(.*\)/# |\1|\2|/p"
echo

输出

# |cat dog |sky|
# |cat dog| sky|
# |cat dog |sky|

# |cat  dog  |sky|
# |cat  dog|  sky|
# |cat  dog  |sky|

# |cat  dog  sky|  |
# |cat  dog  sky|  |
# |cat  dog  |sky  |

2

在我看来,\<.*?\> 只会匹配一系列的单词字符,而 \b.*?\b 则可以匹配一系列的单词字符或非单词字符,因为它也可以接受一个单词的结尾,然后再是另一个单词的开头。如果你强制将两者之间的表达式设置为单词,它们确实会表现得相同。

当然,你可以使用 \b\w\w\b 来复制 \<\> 的行为。所以我想答案是肯定的,这主要是为了可读性。不过话说回来,正则表达式中的大多数转义字符不都是为了可读性吗?


转义字符 \\ 不是为了可读性而存在的,它用于将一个正则表达式运算符与相同字形的字面字符区分开来。 - Peter.O
@fred - 我的意思是转义字符,比如\w\d(不是\本身)通常可以用字符类中的其他字符替换,比如[0-9] - dlras2
Daniel: \<.*\>将匹配由单词字符限定的任何字符串。.*是贪婪的,因此会尽可能匹配多个任意字符。要仅匹配单个单词,您可以使用非贪婪变体:\<.*?\> - phils

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接