如何告诉“grep -w”什么字符组成“单词”?

fre*_*ion 7 grep search regular-expression

$ printf 'asf .test. afd\nasaf foo-test asfdads\n'
asf .test. afd
asaf foo-test asfdads

$ printf 'asf .test. afd\nasaf foo-test asfdads\n' | grep -w test
asf .test. afd
asaf foo-test asfdads
Run Code Online (Sandbox Code Playgroud)

问题:如何匹配“foo-test”?更准确地说,我如何说“-w”使用“-”作为分隔符,但不要使用“。” ?

或者换句话说,我可以告诉grep.是构成的字符中的话,因此,有没有字的边界之间.test

或者除了grep还有其他解决方案吗?

Sté*_*las 11

在早于2.19版本,GNUgrep-w将只考虑单字节字符alnums和下划线(因此在UTF-8语言环境中,只有26 + 26 + 10 + 1(ASCII字母,数字和下划线))作为字成分。所以例如echo Stéphane | grep -w St会匹配。这是在 2.19 中修复的。

但是,您可以手动实现逻辑:

 grep -E '([^[:alnum:]_.]|^)test([^[:alnum:]_.]|$)'
Run Code Online (Sandbox Code Playgroud)

test由任一非字组成或行的开始之前和之后或者非单词基成分或该线的端部。

(以上[:alnum:]匹配您的语言环境中的数字和字母,不仅是 ASCII 的,如果您只想要 ASCII 的,请将语言环境固定为 C)。

如果您不希望将那些周围的非单词成分包含在匹配中(例如因为您使用的是 GNU 的-o),则这次您可以使用 PCRE 正则表达式和环视运算符:

grep -Po '(*UCP)(?<![\w.])test(?![\w.])'
Run Code Online (Sandbox Code Playgroud)

删除(*UCP)和添加LC_ALL=C以仅匹配 ASCII 字母和数字。

(*UCP)在正则表达式的开始告诉PCRE库ú?网卡?颂歌P + roperties必须使用\w

没有它,\w将匹配您的语言环境的字母数字和下划线,但仅适用于单字节字符。这在 UTF-8 语言环境(现在的规范)中不起作用,其中只匹配 ASCII 语言环境。(*UCP)使其也适用于 UTF-8。它将根据 PCRE 自己的字符属性概念进行匹配,该概念可能与您的语言环境不同,但在 GNU 系统上,这与 UTF-8 语言环境定义一样不完整和过时(至少截至 2015-04)。