You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Linux命令筛选出现次数大于1的非重复单词?解决awk重复输出问题

如何用Linux Shell命令筛选出现次数大于1的单词?

需求说明

我需要处理一个文本文件,用sort tt.txt | uniq -c可以统计每个单词的出现次数,示例如下:

# cat tt.txt
test
this
and
that
and
test

# sort tt.txt | uniq -c
      2 and
      2 test
      1 that
      1 this

但我只想返回出现次数大于1的单词,期望输出是:

and
      test

我能用Python的pandas实现,但需要纯Linux Shell脚本的解决方案。

遇到的问题:awk方案的异常

我尝试用awk命令,但结果不符合预期。比如给tt.txt追加三个"to"后:

# echo "to" >> tt.txt
# echo "to" >> tt.txt
# echo "to" >> tt.txt

# awk '++a[$1] > 1' tt.txt
and
test
to
to

为什么"to"会重复出现?

解决方法

方法1:sort+uniq+awk组合(推荐)

先通过sort+uniq -c完成统计,再用awk筛选次数大于1的行,最后去掉计数部分保留单词(如果需要和原输出一致的空格对齐就用第二个命令):

# 仅输出单词
sort tt.txt | uniq -c | awk '$1 > 1 {print $2}'

# 保留空格对齐格式
sort tt.txt | uniq -c | awk '$1 > 1 {sub($1 OFS, ""); print}'

执行后就能得到符合预期的输出:

and
      test

方法2:修复awk的重复问题

原awk命令++a[$1] > 1的问题在于:每处理一行就会递增计数,只要计数大于1就输出当前行。比如"to"出现第三次时,计数变为3,依然满足>1的条件,所以会再次输出,导致重复。

要让每个单词只输出一次,需要先统计所有单词的总次数,再在处理完所有行后统一输出:

# 带空格对齐的版本
awk '{a[$1]++} END {for (word in a) if (a[word]>1) printf "%8s\n", word}' tt.txt

# 不带对齐的版本
awk '{a[$1]++} END {for (word in a) if (a[word]>1) print word}' tt.txt

这个命令会先遍历所有行统计次数,最后在END块里遍历统计结果,只输出次数大于1的单词,每个单词只会出现一次。

内容的提问来源于stack exchange,提问作者shantanuo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 19:10:02