6

我正在尝试读取文件并按特定字段的出现次数对其进行排序。假设我想从日志文件中找出重复次数最多的日期,然后我使用 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

谢谢

4

9 回答 9

8

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

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 上进行的实验确定的,但使用uniq8.3coreutils中的 GNU。BSDuniq -c在一位数之前产生了 3 个前导空格。POSIX 规范说输出的uniq -c格式应如下所示:

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

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

uniq -c | sort -nr | sed 's/^ *[0-9]* //'
于 2012-04-10T06:33:34.250 回答
5

而不是cut -d' ' -f2,尝试

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

也许您需要在开始时再删除一个空白:

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

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

sed -r 's/^[^0-9]*[0-9]+//'
于 2012-04-10T06:36:27.887 回答
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
于 2018-07-08T10:25:57.000 回答
2

另一种解决方案是:

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

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

于 2012-08-10T22:03:46.423 回答
2

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

cat file |sort |uniq -c | awk '{ print $2; }'
于 2018-07-08T10:24:56.540 回答
1

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

 .. | 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-
于 2014-11-03T12:21:39.340 回答
1

添加tr -s到管道链以将多个空格“挤压”到一个空格分隔符中:

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

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

于 2017-01-13T16:46:34.367 回答
0

您可以使用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~
于 2018-07-08T10:25:16.533 回答
0

第一个解决方案
sort在未考虑输入重复时使用。sort有独特的选择-u

  • sort -u file
  • sort -u < file

前任。:

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


如果sort基于重复的ing很重要,则第二种解决方案

  • 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
于 2018-07-08T10:32:25.023 回答