排序和计算行出现的次数

Kok*_*zzu 253 command-line sort

我有Apache日志文件,access.log如何计算该文件中出现的行数?例如的结果cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'

a.php
b.php
a.php
c.php
d.php
b.php
a.php
Run Code Online (Sandbox Code Playgroud)

我想要的结果是:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Run Code Online (Sandbox Code Playgroud)

小智 328

| sort | uniq -c
Run Code Online (Sandbox Code Playgroud)

如评论中所述。

将输出管道sort化为按字母/数字顺序组织输出。

这是一个要求,因为uniq只匹配重复的行,即

a
b
a
Run Code Online (Sandbox Code Playgroud)

如果您uniq在此文本文件上使用,它将返回以下内容:

a
b
a
Run Code Online (Sandbox Code Playgroud)

这是因为两个as 被 - 分隔,b它们不是连续的行。但是,如果您首先将数据按字母顺序排序,例如

a
a
b
Run Code Online (Sandbox Code Playgroud)

然后uniq将删除重复行。该-c的选项uniq计数重复的数量,并提供输出形式:

2 a
1 b
Run Code Online (Sandbox Code Playgroud)

参考:

  • @Jidder,不,那是因为`①.php` 在我的语言环境中与`②.php` 的排序相同,因为在我的语言环境中没有为那些`①` 和`②` 字符定义排序顺序。如果你想要任何字节值的 _unique_ 值(记住文件路径不一定是文本),那么你需要将语言环境固定为 C:`| LC_ALL=C 排序 | LC_ALL=C uniq -c`。 (6认同)
  • 为了对生成的计数文件进行排序,您应该考虑添加“sort -nr”作为下面的@eduard-florinescu 答案。 (3认同)

Edu*_*scu 176

[your command] | sort | uniq -c | sort -nr
Run Code Online (Sandbox Code Playgroud)

接受的答案几乎完整,您可能希望sort -nr在最后添加一个额外的内容,以使用最常出现的行对结果进行排序

唯一选项:

-c, --count
       prefix lines by the number of occurrences
Run Code Online (Sandbox Code Playgroud)

排序选项:

-n, --numeric-sort
       compare according to string numerical value
-r, --reverse
       reverse the result of comparisons
Run Code Online (Sandbox Code Playgroud)

在特定情况下,您正在排序的行是数字,您需要使用sort -gr而不是sort -nr,请参阅评论

  • 实际上,当数据是数字时,`-gr` 效果更好。试试这两个例子,区别只在于 g 和 n 标志: `echo "1 11 1 2" | tr ' ' '\n' | 排序 | uniq -c | sort -nr` 和 `echo "1 11 1 2" | tr ' ' '\n' | 排序 | uniq -c | 排序-gr`。第一个排序不正确,但第二个排序不正确。 (5认同)
  • 使用上面的选项,我在“23344”之前得到“1”。使用 `sort -gr` 可以解决这个问题。`-g`:根据一般数值进行比较(而不是`-n`:根据字符串数值进行比较)。 (4认同)
  • 非常感谢让我知道 `-n` 选项。 (3认同)
  • 很好的答案,这是我用来从带有句子的文件中获取字数的方法:`tr ' ' '\n' < $FILE | 排序 | uniq -c | sort -nr > wordcount.txt`。第一个命令用换行符替换空格,允许命令的其余部分按预期工作。 (3认同)
  • 对于 coreutils 9.1 上的给定示例,“sort -g”和“sort -n”给出了相同的输出(也使用 LC_ALL=C 进行了测试)。 (2认同)

小智 21

您可以在awk上使用关联数组,然后 - 可选地 -排序

$ awk ' { tot[$0]++ } END { for (i in tot) print tot[i],i } ' access.log | sort
Run Code Online (Sandbox Code Playgroud)

输出:

1 c.php
1 d.php
2 b.php
3 a.php
Run Code Online (Sandbox Code Playgroud)

  • 如果输入列表非常大,这种方法非常有价值,因为它不需要将整个列表读入内存然后对其进行排序。 (5认同)

小智 5

在本例中,您可以使用clickhouse-client工具来处理文件,例如处理具有单列的 sql 表:

clickhouse-local --query \
"select data, count() from file('access.log', TSV, 'data String') group by data order by count(*) desc limit 10"
Run Code Online (Sandbox Code Playgroud)

我的简短实验表明它比

cat access.log | sort | uniq -c | sort -nr | head 10
Run Code Online (Sandbox Code Playgroud)

  • XD 这是 Clickhouse 非常酷的用例! (2认同)