我有一个字符串文件:
string-string-123
string-string-123
string-string-123
string-string-12345
string-string-12345
string-string-12345-123
如何在bash中检索最常见的行(
string-string-123
)?我有一个字符串文件:
string-string-123
string-string-123
string-string-123
string-string-12345
string-string-12345
string-string-12345-123
string-string-123
)?你可以在 sort
命令中使用 uniq
选项。
sort file | uniq -c | sort -n -r
awk '{++a[$0]}END{for(i in a)if(a[i]>max){max=a[i];k=i}print k}' file
a
用于记录每一行的计数。读完文件后,我们遍历数组并找到计数最多的那一行。END
块中的循环:awk 'max < ++c[$0] {max = c[$0]; line = $0} END {print line}' file
感谢格伦·杰克曼提供这个有用的建议。
正如大家指出的那样,以上两种方法在出现并列最高次数的情况下只会打印其中一行。以下版本将打印所有并列最高次数的行:
awk 'max<++c[$0] {max=c[$0]} END {for(i in c)if(c[i]==max)print i}' file
awk '{if (max < ++c[$0]) {max = c[$0]; line = $0}} END {print line}'
- glenn jackmanawk '{b[a[$0]++]=$0}END{asort(b);print b[1]}'
。 - user4453924Tom Fenech的优雅的awk
答案在修订版中表现出色,可以打印所有最常出现的行,但是对于大文件可能不适用,因为所有不同的输入行都存储在关联数组中,这可能是一个问题,如果有许多非重复行;尽管如此,它比下面讨论的方法要快得多。
Grzegorz Żur的答案优雅地结合了多个实用程序来隐式地产生所需的结果,但是:
虽然您可以将Grzegorz Żur's answer管道传输到head
以限制显示的行数,但通常情况下不能假定有固定数量的行。
在Grzegorz的答案基础上,这里提供了一个通用的解决方案,它显示所有最常出现的行 - 不管有多少行 - 以及仅仅它们:
sort file | uniq -c | sort -n -r | awk 'NR==1 {prev=$1} $1!=prev {exit} 1'
sort file | uniq -c | sort -n -r | awk 'NR==1 {prev=$1} $1!=prev {exit} 1' |
sed 's/^ *[0-9]\{1,\} //'
Grzegorz Żur的回答的解释:
uniq -c
输出一组唯一的输入行,前缀为它们各自的出现次数(-c
),后跟一个空格。sort -n -r
然后按数字排序结果行(-n
),按降序排列(-r
),以便最常出现的行位于顶部。
-k
,则sort
通常会尝试按整个输入行进行排序,但-n
仅使用被识别为整数的最长前缀进行排序,这正是此处所需的。我awk
命令的解释:
NR==1 {prev=$1}
将第一个空格分隔字段 ($1
) 存储在变量 prev
中,用于处理输入的第一行 (NR==1
)。$1!=prev {exit}
如果第一个空格分隔字段与上一行不同,则终止处理 - 这意味着已到达非顶部行,并且不需要再打印更多行。1
是 { print }
的简写,表示应按原样打印正在处理的输入行。我sed
命令的解释:
^ *[0-9]\{1,\}
匹配每个输出行的数字前缀(表示出现次数),如uniq -c
最初生成的那样。s/...//
意味着前缀被替换为一个空字符串,即有效地删除。