需要命令使用 grep 查找文件中唯一单词的数量

尝试使用 grep 以及 uniq 和 sort,但需要找到一种仅使用 grep 和 wc 命令的方法。这是我能够做到的两种方法,但我需要仅使用 grep ..

$ grep -oE '\w+' 'file.txt' | sort | uniq | wc -l
$ grep -oE '\w+' 'file.txt' > temp.txt && awk '!seen[$0]++' temp.txt | wc -l

输入文件示例:

one two three four five
two four one six
eight three seven five

输出:唯一字数:8

是否可以首先使用 grep -oE ‘\w+’ file.txt 命令提取单词,然后对每个单词执行 grep 到一个空文件,如果 grep 找不到该文件中存在的单词,则将单词附加到文件中.这样只有那些在新文件中找不到的单词才会被附加到它吗?可以使用 grep 来做到这一点吗?

9

  • 1
    您能否添加一个带有预期输出的最小(5-10 行)示例?


    – 

  • @AndreWildberg 我已经添加了预期的输出


    – 

  • 万分感谢!那么该文件只有单词,有些在一行,但也有换行符?


    – 

  • 1
    @AndreWildberg是的,该文件只有单词,例如一个段落,其中多行包含单词


    – 


  • 顺便说一下,1) sort | uniq=sort -u和 2) grep -oE '\w+' 'file.txt' > temp.txt && awk '!seen[$0]++' temp.txt= grep -oE '\w+' 'file.txt' | awk '!seen[$0]++'


    – 



3 个回答
3

既然你grep有,-o我假设它也有-P-z

grep -zPo '(?s)(\b\w+\b)(?!.*\b\1\b)' file.txt |
grep -zc ^
  • 使用-zmakegrep将整个文件视为单个“行”(因为其中不应有空值)
  • 用于-P启用 Perl 兼容的正则表达式 (PCRE),允许环视断言
  • (?s)– 告诉 PCRE.也应该匹配换行符
  • 使用负向先行(?!)查找每个单词的最终出现位置(即单词后面没有跟任何单词)

    • \b\w+\b\b\1\b排除部分单词
  • 我们使用前瞻,以便前瞻文本不会被匹配消耗,并且可以在查找更多最终单词时重复使用
  • 用于-o在自己的“行”上输出每个匹配项(因为-z,空值被用作行结束字符)
  • 获取生成的唯一单词列表并输出“行”数

这对于较大的文件来说非常慢。

6

  • 1
    我现在正在思考该脚本的作用。根据 GNU grep 手册页有关-P“此选项与 -z (–null-data) 选项结合时是实验性的”,您知道上面的任何内容在这种情况下是否脆弱吗?


    – 

  • 1
    @EdMorton 鉴于 RE 遭受灾难性的回溯,脆弱性是其最不重要的问题


    – 

  • 1
    @EdMorton regex101 对于 3500 个单词输入达到 40M 步,并在 4000 个单词时超时,远远超出了这个范围,这可能会中断


    – 

  • 1
    好吧,OP只是问是否可以完成,而不是是否可以稳健、可移植、高效、可靠等完成,所以在我看来,这是一个很好的答案:-)。


    – 

  • 是的,对于任何大尺寸的输入,仅使用sort -u就更加稳健


    – 

由于 awk 也被标记,因此一种仅使用(几乎任何)的方法awk,返回关联数组的长度,其中索引是单词。

% awk '{for(i=1;i<=NF;i++){A[$i]++}} END{print length(A)}' file
8

测试用

  • GNU awk 3.1.8/4.2.1/5.3.0
  • 诺克 20221215
  • 原始 awk 20121220
  • 莫克 20240123

0

你想要做的事情用 justgrepgrep+是不可能的wc(除非你使用 GNUgrep及其扩展和每个警告)。

鉴于此,如果您确实只想使用一种工具,则使用 GNU Awk 进行多字符处理RS并假设一个由空格分隔的“单词”文件作为输入:

$ awk -v RS='\\s+' '{unq[$0]} END{print "unique word count:", length(unq)}' file.txt
unique word count: 8

或使用正则表达式来识别“单词”:

$ awk -v RS='\\w+' 'RT{unq[RT]} END{print "unique word count:", length(unq)}' file.txt
unique word count: 8

0