grep 仅由大写字母组成的整个单词

grep whole words made of only uppercase letters

看起来这很简单,但我遇到了麻烦。

我有一个文本文档,例如,看起来像这样:

This is a
TEXT DOCUMENT with
SOME capitalized words
BUT NOT all of them are
ALL CAPS
iPhone

我想要的是解析此文档并仅匹配仅由大写字母组成的整个单词,如下所示:

TEXT DOCUMENT
SOME
BUT NOT
ALL CAPS

我写了这个:

grep -o "\w[[:upper:]]\w" Untitled.txt

这已经很接近了,但是,唉,returns 这个:

TEX
DOC
UME
SOM
BUT
NOT
ALL
CAP
iPh

...坦率地说,我不明白。

那么:我可能遗漏了什么? egrep 在 OS X 下工作得不是很好,因为我受到 FreeBSD 的 grep (grep (BSD grep) 2.5.1-FreeBSD) 的限制,我猜,我为 egrep 找到的很多解决方案似乎他们会工作不按预期工作。

你错过了 * 而且 \w 是任何单词字符。正确的正则表达式是:

\<[[:upper:]][[:upper:]]*\>

\< \> 匹配单词边界

示例输出在同一行显示多个 space 分隔的大写单词,这可以通过

实现
$ grep -ow '[[:upper:]][[:upper:][:space:]]*[[:upper:]]' infile
TEXT DOCUMENT
SOME
BUT NOT
ALL CAPS

任何以大写字符开始和结束的序列,它们之间有大写字符或白色space。 -o returns 仅匹配,-w 确保我们不匹配 WORDlowercase.

你可以使用这个命令:

grep -o -E "\<[[:upper:]]+\>" Untitled.txt
  • -E 激活扩展正则表达式,这使得 + 可用,代表 1 次或多次重复
  • \<\> 是标记单词开始和结束的锚点
  • 整个正则表达式表示构成整个单词的一个或多个大写字符的序列

你原来的正则表达式给了你三个字母匹配,因为 \w 代表 [_[:alnum:]],所以你指示 grep 匹配由三个字符组成的东西:

  • 第一个和第三个来自[_[:alnum:]]
  • [[:upper:]] 范围内的第二个

补充:

grep-E 选项允许使用 扩展的 正则表达式,其中包括量词 + 来表示 一个或多个,这简化了解决方案:

 grep -Eo '\<[[:upper:]]+\>' Untitled.txt

此外,如 中所述,-w 可用于匹配单词边界,而无需将其指定为正则表达式的一部分:

 grep -Ewo '[[:upper:]]+' Untitled.txt

但是请注意,-w 是一个 非标准 选项(但 BSD/OSX 和 GNU grep 都实现了它)。


至于egrep:它只不过是grep -E的一个(有效的)别名,如前所述,它激活了对extended regular的支持表达式,但确切的功能集是 平台相关的

此外,只有 GNU grep 支持 -P 选项来支持 PCRE(Perl 兼容的正则表达式),它提供了更多的特性和灵活性。

"old school" RE 的字符数会更少:

grep -o '[A-Z][A-Z]*' Untitled.txt

它使用 -o 选项仅打印匹配的单词并匹配大写字母 A 到 Z。

添加 -w 来搜索词和 -E 来调用扩展的正则表达式允许这个更短:

grep -woE '[A-Z]+\>' Untitled.txt