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

如何告诉“grep -w”哪些字符组成“单词”?
$ 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

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

或者换句话说,我能看出grep.是组成的角色之一吗?,因此不存在字边界.和之间test

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

答案1

在 2.19 之前的版本中,GNUgrep只会-w将单字节字符数字和下划线(因此在 UTF-8 语言环境中,只有 26+26+10+1(ASCII 字母、数字和下划线))视为单词成分。例如echo Stéphane | grep -w St会匹配。该问题已在 2.19 中修复。

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

 grep -E '([^[:alnum:]_.]|^)test([^[:alnum:]_.]|$)'

test前面是非单词成分或行的开头,后面是非单词成分或行的结尾。

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

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

grep -Po '(*UCP)(?<![\w.])test(?![\w.])'

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

(*UCP)在正则表达式的开头使用告诉 PCRE 库U̲niC̲ode 性能必须用于\w.

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

相关内容