Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在bash中查找文件中最常用的行_Linux_Bash_Text Processing - Fatal编程技术网

Linux 在bash中查找文件中最常用的行

Linux 在bash中查找文件中最常用的行,linux,bash,text-processing,Linux,Bash,Text Processing,我有一个字符串文件: string-string-123 string-string-123 string-string-123 string-string-12345 string-string-12345 string-string-12345-123 如何检索bash中最常用的行(string-string-123)?您可以使用awk来执行此操作: awk '{++a[$0]}END{for(i in a)if(a[i]>max){max=a[i];k=i}print k}' fi

我有一个字符串文件:

string-string-123
string-string-123
string-string-123
string-string-12345
string-string-12345
string-string-12345-123

如何检索bash中最常用的行(
string-string-123
)?

您可以使用awk来执行此操作:

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];line=$0}结束{print line}文件
谢谢你的建议


有人正确地指出,上述两种方法只会打印出平局中最常见的一行。以下版本将打印出所有最常出现的行:

awk 'max<++c[$0] {max=c[$0]} END {for(i in c)if(c[i]==max)print i}' file

awk'max您可以使用
sort
uniq

sort file | uniq -c | sort -n -r
  • 非常有效[在修订版中,在出现平局时打印所有最常出现的行]。
    但是,它可能不适用于大文件,因为所有不同的输入行都存储在内存中的关联数组中,如果有许多非重复行,这可能是一个问题;也就是说,它比下面讨论的方法快得多

  • 优雅地组合多个实用程序以隐式生成所需结果,但:

    • 打印所有不同的行(首先是最高频率计数)
    • 输出行的前缀是它们的出现次数(这实际上可能是可取的)
虽然可以通过管道连接到
头部
来限制显示的行数,但通常不能假定固定的行数

基于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,\} //'

解释:

  • uniq-c
    输出一组唯一的输入行,其前缀为各自的出现计数(
    -c
    ),后跟一个空格
  • 排序-n-r
    然后按降序(
    -r
    )对结果行进行数字排序(
    -n
    ),以便最频繁出现的行位于顶部。
    • 请注意,
      sort
      ,如果未指定
      -k
      ,通常会尝试按整个输入行进行排序,但
      -n
      只会导致识别为整数的最长前缀用于排序,这正是此处所需的

我的
awk
命令说明:

  • NR==1{prev=$1}
    在变量
    prev
    中存储第一个空格分隔字段(
    NR==1
  • $1=prev{exit}
    终止处理,如果第一个空格分隔的字段与前一行的字段不同-这意味着已到达非最上面的行,并且不再需要打印更多的行
  • 1
    {print}
    的缩写,意思是手头的输入行应该按原样打印

我的
sed
命令说明:

  • ^*[0-9]\{1,\}
    匹配每个输出行的数字前缀(表示出现计数),正如(最初)由
    uniq-c产生的一样
  • 应用
    s/../
    意味着前缀被替换为空字符串,即被有效删除

将“max”逻辑移出结束块以获得相似性:
awk'{if(max<++c[$0]){max=c[$0];line=$0}}}结束{print line}'
这是一个优雅的解决方案,但请注意,如果最常出现的行有关联,则您的解决方案将只打印其中一行,而哪一行并不明显。@mklement0这是一个公平点。我已经添加了另一个版本,可以打印所有的图片。谢谢你的更新-做得很好。唯一剩下的问题是,这种方法可能无法处理大型输入文件,因为您将所有不同的输入行读取到内存中,这可能是输入中大量不同行的问题。另一方面,您的方法比
sort
/
uniq
方法快得多。另一种方法是使用asort
awk'{b[a[$0]+]=$0}END{asort(b);打印b[1]}'
可能的重复