Bash Uniq选项
我有20个文件。在每个文件中,我都列出了出现的单词及其频率 例如:Bash Uniq选项,bash,shell,Bash,Shell,我有20个文件。在每个文件中,我都列出了出现的单词及其频率 例如: 2 représentant 3 reproduire 2 réseau 1 rester 3 reste 1 résumer 我使用这个命令在这20个文件之间进行合并 cat *.txt > tous.txt | sort | uniq -ci | sort -k3 结果是,例如: 2 2 représentant 1 6 représentant 5 3 reproduire 2
2 représentant
3 reproduire
2 réseau
1 rester
3 reste
1 résumer
我使用这个命令在这20个文件之间进行合并
cat *.txt > tous.txt | sort | uniq -ci | sort -k3
结果是,例如:
2 2 représentant
1 6 représentant
5 3 reproduire
2 3 reproduire
6 3 réseau
1 1 réseau
etc..
但是我想要的是让它计算每个单词的出现次数,而不需要写很多次。我想要的是:
8 representant
6 reproduire
4 réseau
...
我可以用awk来做:
awk '{tab[$2]+=$1} END {for(i in tab){printf("%7d %s\n", tab[i], i) | "sort -k2"}}' ~/Bureau/Projet/data/dico/*.dico.forme.txt > ~/Bureau/Projet/data/input/black.txt
对于ex if?还有其他建议吗?最简单的方法是首先不要进行计数。使用
uniq
似乎没有简单的方法,但您可以使用Awk或循环进行计数
sort -k2,2 all.txt | awk '{a[$2] += $1} END{for (i in a) print a[i],i}'
输出:
5 hi
7 test
6 try
while
循环(效率较低)执行此操作:
不需要将中间结果存储在
tous.txt
中,也不需要将整个数组保存在内存中,尽管这是一个小的效率攻击,除非数据集很大,否则不会产生太大的影响
sort -k2,2 *.txt |
awk 'NR>1 && $2 != prev { print sum, prev; sum = 0 }
{ prev = $2; sum += $1 }
END { print sum, prev }'
注意END
块如何重复(部分)主流。(缺少最后一行输出是这种通用方法的常见错误。)
正如其他人已经建议的那样,如果您可以避免使用
*.txt
文件,直接使用整个原始输入进行排序| uniq-c
,这可能会更加优雅和高效。使用简单的排序和uniq管道无法实现这一点。仅仅使用这些工具来获取预先存在的计数并求和是没有好方法的。您可以使用更复杂的Bash脚本来完成,但Awk是更简单且可能是最好的方法。根据您的描述,单词出现总数不应该是:10 représentant
,21 reproduire
,19 réseau
,也就是说,每行中列出的单词出现总数乘以这些计数出现的次数,再加上同一单词的任何其他此类计数?é将不计算在内,因为请向我们显示您使用的确切命令。您问题中的命令:cat*.txt>tous.txt | sort | uniq-ci | sort-k3
不会执行您所说的操作。cat*.txt
的输出被写入tous.txt
,并且将不能作为sort
的输入。我同意“首先不要进行计数”,但其余的都很糟糕。恐怕不行。您和您仍然不必要地使用临时文件,并且事后未能清理;但更一般地说,OP的Awk脚本在有效解决问题方面已经做得更好了。您的Awk重构有点改进,但它失去了排序顺序。在任何情况下,我都会犹豫是否删除我的否决票,只要您的shell脚本甚至没有在每次迭代中通过读取整个文件来grep
,这是非常低效的。使用echo
和backticks也会引起一些奇怪的嗅觉感觉,虽然从技术上讲这不是一个问题,但我不情愿地取消了我对你所付出的所有努力的否决票,但实际上,这个答案的TLDR是,“我没有比OP的Awk脚本更好的解决方案。”。请注意,*.txt
将与tous.txt
匹配,因此请在运行此操作之前删除它。
5 hi
7 test
6 try
while read -r a; do
echo "$(grep -w "$a" all.txt|cut -d ' ' -f1|paste -sd+|bc)" "$a"
done< <(cut -d ' ' -f2 all.txt|sort -u)
while read -r a b; do
yes "$b" |head -n "$a"
done <all.txt | sort| uniq -c
sort -k2,2 *.txt |
awk 'NR>1 && $2 != prev { print sum, prev; sum = 0 }
{ prev = $2; sum += $1 }
END { print sum, prev }'