【问题标题】:Need to remove the count from the output when using "uniq -c" command使用“uniq -c”命令时需要从输出中删除计数
【发布时间】:2012-04-10 06:27:13
【问题描述】:

我正在尝试读取文件并按特定字段的出现次数对其进行排序。假设我想从日志文件中找出重复次数最多的日期,然后我使用 uniq -c 选项并按降序对其进行排序。像这样的

uniq -c | sort -nr 

这将产生一些像这样的输出 -

809 23/Dec/2008:19:20

实际上是计数的第一个字段对我来说是个问题....我想从上面的输出中得到一个日期,但我无法得到这个。我尝试使用 cut 命令并做到了这一点

uniq -c | sort -nr | cut -d' ' -f2 

但这只是打印空白......请有人可以帮助我只获取日期并取消计数。我只想要

23/Dec/2008:19:20

谢谢

【问题讨论】:

  • 你确定你的输出是这样的吗?我试过echo '809 23/Dec/2008:19:20' | cut -d' ' -f2,效果很好
  • 根据正在使用的uniq 的实现,在重复计数809 之前可能有零个或多个空格。如果没有前导空格,原始表达式可以正常工作。因为uniq -c 的某些实现确实会产生前导空格,所以会遇到问题。
  • 乔纳森..这是一个完美的猜测....我看到计数之前有一个空格。
  • 不管输入:先排序然后uniq
  • 可以显示输入数据吗?

标签: linux bash shell unix


【解决方案1】:

uniq 的计数前面有空格,除非计数超过 7 位,因此您需要执行以下操作:

uniq -c | sort -nr | cut -c 9-

获取列(字符位置) 9 向上。或者你可以使用sed:

uniq -c | sort -nr | sed 's/^.\{8\}//'

或:

uniq -c | sort -nr | sed 's/^ *[0-9]* //'

面对 10,000,000 或更多的重复计数,第二个选项非常可靠;如果您认为这可能是一个问题,它可能比cut 替代方案更好。毫无疑问,还有其他选择。


警告:计数是通过 Mac OS X 10.7.3 上的实验确定的,但使用来自 coreutils 8.3 的 GNU uniq。 BSD uniq -c 在一位数之前产生了 3 个前导空格。 POSIX 规范说来自uniq -c 的输出应格式化为:

printf("%d %s", repeat_count, line);

不会有任何前导空格。鉴于输出格式可能存在差异,带有[0-9] 正则表达式的sed 脚本是处理来自uniq -c 的观察和理论输出的可变性的最可靠方法:

uniq -c | sort -nr | sed 's/^ *[0-9]* //'

【讨论】:

  • 谢谢 .... 它帮助很大,我学到了一个新的命令 sed。我还是这个 shell 脚本的新手。
【解决方案2】:

试试cut -d' ' -f2,试试

awk '{$1="";print}'

也许你需要在开头再删除一个空白:

awk '{$1="";print}' | sed 's/^.//'

或完全使用 sed,保留原始空白:

sed -r 's/^[^0-9]*[0-9]+//'

【讨论】:

  • 不错:通用解决方案,独立于操作系统和uniq 版本。
【解决方案3】:

关注awk 可能会对您有所帮助。

awk '{a[$0]++} END{for(i in a){print a[i],i | "sort -k2"}}'  Input_file

解决方案 2: 如果您希望输出的顺序与输入的顺序相同,但与排序不同。

awk '!a[$0]++{b[++count]=$0} {c[$0]++} END{for(i=1;i<=count;i++){print c[b[i]],b[i]}}'  Input_file

【讨论】:

    【解决方案4】:

    另一种解决方案是:

    uniq -c | sort -nr | awk '{print $1, $2}'
    

    您也可以轻松打印单个字段。

    【讨论】:

    • 这仅在第二个字段不包含任何空格时才有效。
    【解决方案5】:

    使用(因为您在问题中使用 -f2)

    cat file |sort |uniq -c | awk '{ print $2; }'
    

    【讨论】:

      【解决方案6】:

      如果您想在下游使用计数字段,以下命令会将其重新格式化为“管道友好”制表符分隔格式,不带左填充:

       .. | sort | uniq -c | sed -r 's/^ +([0-9]+) /\1\t/'
      

      对于原始任务,这有​​点矫枉过正,但在重新格式化后,cut 可用于删除该字段,正如 OP 所期望的那样:

       .. | sort | uniq -c | sed -r 's/^ +([0-9]+) /\1\t/' | cut -d $'\t' -f2-
      

      【讨论】:

        【解决方案7】:

        在管道链中添加tr -s,将多个空格“挤”成一个空格分隔符:

        uniq -c | tr -s ' ' | cut -d ' ' -f3
        

        tr 在一些不起眼的地方非常有用。不幸的是,它并没有摆脱第一个前导空格,因此 -f3

        【讨论】:

          【解决方案8】:

          您可以使用sed 去除前导空格和uniq -c 打印的数字

          sort file | uniq -c | sed 's/^ *[0-9]* //'
          

          我会用一个例子来说明这一点。考虑一个文件

          winebottles.mkv
          winebottles.mov
          winebottles.xges
          winebottles.xges~
          winebottles.mkv
          winebottles.mov
          winebottles.xges
          winebottles.xges~
          

          命令

          sort file | uniq -c | sed 's/^ *[0-9]* //'
          

          会回来

          winebottles.mkv
          winebottles.mov
          winebottles.xges
          winebottles.xges~
          

          【讨论】:

          • 实际上这个解决方案只对仅由字母组成的文件有用。因此,它将适合提供的示例,但不适用于实际情况。
          • @Shred 我添加了一个示例来说明 sed 去除前缀的方式。
          • 尽管失去useless cat
          【解决方案9】:

          第一个解决方案
          仅在未考虑输入重复时使用sortsort 有唯一选项 -u

          • sort -u file
          • sort -u &lt; file

          例如:

          $ cat > file
          a
          b
          c
          a
          a
          g
          d
          d
          $ sort -u file
          a
          b
          c
          d
          g
          

          第二种解决方案
          如果基于重复的sorting 很重要

          • sort txt | uniq -c | sort -k1 -nr | sed 's/^ \+[0-9]\+ //g'
          • sort txt | uniq -c | sort -k1 -nr | perl -lpe 's/^ +[\d]+ +//g'

          有这个输出:

          a
          d
          g
          c
          b
          

          【讨论】:

          • 是的 sort 有这个选项,但是你不能让 uniq 产生额外的信息(在这种情况下是计数),因为你有仅在那时的唯一记录
          猜你喜欢
          • 1970-01-01
          • 2020-01-17
          • 1970-01-01
          • 1970-01-01
          • 2012-09-22
          • 1970-01-01
          • 1970-01-01
          • 2014-03-31
          • 2022-01-01
          相关资源
          最近更新 更多