Ale*_*lex 7 linux bash text-processing
我有一个字符串文件:
string-string-123
string-string-123
string-string-123
string-string-12345
string-string-12345
string-string-12345-123
Run Code Online (Sandbox Code Playgroud)
如何在bash(string-string-123)中检索最常见的行?
Grz*_*Żur 16
你可以用sort与uniq
sort file | uniq -c | sort -n -r
Run Code Online (Sandbox Code Playgroud)
你可以使用awk来做到这一点:
awk '{++a[$0]}END{for(i in a)if(a[i]>max){max=a[i];k=i}print k}' file
Run Code Online (Sandbox Code Playgroud)
该数组a保持每行的计数.读取文件后,我们遍历它并找到具有最大计数的行.
或者,您可以END通过在处理文件期间分配行来跳过块中的循环:
awk 'max < ++c[$0] {max = c[$0]; line = $0} END {print line}' file
Run Code Online (Sandbox Code Playgroud)
感谢格伦杰克曼提出这个有用的建议.
正确地指出,上述两种方法仅打印出平局情况下最常出现的一条线.以下版本将打印出所有最常出现的行:
awk 'max<++c[$0] {max=c[$0]} END {for(i in c)if(c[i]==max)print i}' file
Run Code Online (Sandbox Code Playgroud)
汤姆·费内奇(Tom Fenech)优雅的awk答案非常有效[在修正版本中,在出现平局时打印所有最常出现的行]。
\n但是,它可能不适合大文件,因为所有不同的输入行都存储在内存中的关联数组中,如果有许多非重复行,这可能会成为问题;也就是说,它比下面讨论的方法要快得多。
Grzegorz \xc5\xbbur\ 的答案优雅地隐式地结合了多个实用程序产生所需的结果,但是:
\n\n虽然您可以通过管道传递Grzegorz \xc5\xbbur\ 的答案来head限制显示的行数,但您不能假设固定的限制显示的行数,但通常
基于 Grzegorz 的答案,这里有一个通用解决方案,显示所有最常出现的行 - 无论有多少行 - 并且仅显示它们:
\n\nsort file | uniq -c | sort -n -r | awk \'NR==1 {prev=$1} $1!=prev {exit} 1\'\nRun Code Online (Sandbox Code Playgroud)\n\n如果您不希望输出行以出现次数为前缀:
\n\nsort file | uniq -c | sort -n -r | awk \'NR==1 {prev=$1} $1!=prev {exit} 1\' | \n sed \'s/^ *[0-9]\\{1,\\} //\'\nRun Code Online (Sandbox Code Playgroud)\n\nuniq -c输出一组唯一的输入行,以其各自的出现次数为前缀(-c ),后跟一个空格。sort -n -r-n然后按数字 ( ) 和降序 ( )对结果行进行排序-r,以便最常出现的行位于顶部。\n\nsort,如果-k未指定,通常会尝试按整个输入行进行排序,但-n只会将被识别为整数的最长前缀用于排序,这正是此处所需要的。我的命令的解释awk:
NR==1 {prev=$1}将第一个空格分隔的字段 ( ) 存储在第一个输入行 ( )的$1变量中prevNR==1$1!=prev {exit}如果第一个空格分隔字段与前一行不同,则终止处理 - 这意味着已到达非最顶层行,并且不再需要打印任何行。1是简写,{ print }表示手头的输入行应按原样打印。我的命令的解释sed:
^ *[0-9]\\{1,\\}匹配每个输出行的数字前缀(表示出现次数),(最初)由uniq -c s/...//意味着前缀被替换为空字符串,即有效删除。