在 linux 的文本文件中打印单词(即 7 个​​字母)

Print words(that are 7 letters) in a text file in linux

我的文件中 7 个字母的单词代码:

cat file.txt | tr -cs "[:alnum:]" "\n"| tr "[:lower:]" "[:upper:]" | awk '{h[]++}END{for (i in h){print h[i]" "i}}'| grep -w "\w\{7\}" -w | sort -nr | cat -n | head -n 5

这是输出:this picture shows the top 5 words written

这是文件 link: https://www.gutenberg.org/cache/epub/996/file.txt

请您尝试以下操作:

tr [:lower:] [:upper:] < uly.txt | awk '
{
    for (i=1; i<=NF; i++) {
        sub(/[^[:alnum:]]+$/, "", $i)
        if (length($i) >= 7) h[$i]++
    }
}
END {
    for (i in h) {print h[i]" "i}
}' | sort -nr | cat -n | head -n 5

输出:

     1  3 QUIXOTE
     2  3 PROJECT
     3  3 GUTENBERG
     4  2 LOCATED
     5  2 HISTORY

如果您使用的是 GNU AWK,您通常可以执行其他文本处理命令所执行的操作,我将从

开始介绍后续步骤
cat uly.txt | tr -cs "[:alnum:]" "\n"| tr "[:lower:]" "[:upper:]" | awk '{h[]++}END{for (i in h){print h[i]" "i}}'| grep -w "\w\{7\}" -w | sort -nr | cat -n | head -n 5

首先 GNU AWKString Functions 中有 tolower 所以我们可以用它代替 tr 进行小写

cat uly.txt | tr -cs "[:alnum:]" "\n"| awk '{h[tolower()]++}END{for (i in h){print h[i]" "i}}'| grep -w "\w\{7\}" -w | sort -nr | cat -n | head -n 5

还有一个length函数可以return个字符,所以我们可以用它来代替grep如下

cat uly.txt | tr -cs "[:alnum:]" "\n"| awk 'length()==7{h[tolower()]++}END{for (i in h){print h[i]" "i}}'| sort -nr | cat -n | head -n 5

条件先于动作意味着我们只在满足条件时才执行动作,请注意,这也会导致内存使用量减少,因为不会保留不同长度单词的信息。

GNU AWK 能够以多种方式对数组进行排序,Using Predefined Array Scanning Orders with gawk 中对此进行了描述,因为您使用值来存储数字并希望按降序排列(最常见到最不常见),您应该使用@val_num_desc。这允许替换 sort

cat uly.txt | tr -cs "[:alnum:]" "\n"| awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_desc"}length()==7{h[tolower()]++}END{for (i in h){print h[i]" "i}}'| cat -n | head -n 5

for 循环中获取后续数字可以使用增量运算符之一完成,我会使用 increment-then-return (变量前加号)而不是 return-then-increment (变量后加号)作为您希望编号从 1 而不是 0 开始。这将用于代替 cat -n

cat uly.txt | tr -cs "[:alnum:]" "\n"| awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_desc"}length()==7{h[tolower()]++}END{for (i in h){print ++j" "h[i]" "i}}'| head -n 5

我使用了 j 变量,因为它还没有被使用过。现在我们可以访问行数,很容易在输出 5 个单词后结束处理,这将替换 head -n 5

cat uly.txt | tr -cs "[:alnum:]" "\n"| awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_desc"}length()==7{h[tolower()]++}END{for (i in h){print ++j" "h[i]" "i;if(j>=5){exit}}}'

Exit statement 允许您结束程序。如果您的文件很大,但只处理其中相对较小的一部分就可以得到所需的答案,这尤其方便。

我们可以通过提供行分隔符RS来告知GNU AWK它应该考虑什么行,而不是使用tr预处理文件) 在这种情况下

cat uly.txt | awk 'BEGIN{RS="[^[:alnum:]]+";PROCINFO["sorted_in"]="@val_num_desc"}length()==7{h[tolower()]++}END{for (i in h){print ++j" "h[i]" "i;if(j>=5){exit}}}'

[^[:alnum:]]+ 意思是 1 个或多个 (+) 除了 (^) 个字母数字字符 ([:alnum:])。最后,GNU AWK 不限于使用标准输入 - 您可以使用参数来传递文件进行处理,因此我们可以使用它来替换 cat 以获取

awk 'BEGIN{RS="[^[:alnum:]]+";PROCINFO["sorted_in"]="@val_num_desc"}length()==7{h[tolower()]++}END{for (i in h){print ++j" "h[i]" "i;if(j>=5){exit}}}' uly.txt

请注意,将 cat 的管道输出传输到本身可以读取文件的工具中通常被认为是反模式,甚至有自己的名称:猫的无用使用