【问题标题】:Sorting list in bash by value from keyvalue pair key=value从键值对 key=value 中按值对 bash 中的列表进行排序
【发布时间】:2021-02-24 17:24:37
【问题描述】:

我有一个这样的请求日志:

[11/Jun/2020:15:35:20 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=72161.647 memory=2 cpu=0.01%
[11/Jun/2020:15:22:13 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=70564.992 memory=2 cpu=0.00%
[11/Jun/2020:15:35:26 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=70252.369 memory=2 cpu=0.00%
[11/Jun/2020:15:01:02 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=60159.409 memory=2 cpu=0.03%
[11/Jun/2020:14:59:03 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=106956.770 memory=2 cpu=0.01%
[11/Jun/2020:15:37:56 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=60014.014 memory=2 cpu=0.00%
[11/Jun/2020:16:45:38 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=61264.044 memory=2 cpu=0.02%
[11/Jun/2020:15:01:48 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=58733.325 memory=2 cpu=0.02%
[11/Jun/2020:15:31:35 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=68882.501 memory=2 cpu=0.03%
[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=57021.375 memory=2 cpu=0.00%
[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=137172.179 memory=2 cpu=0.01%
[11/Jun/2020:15:35:39 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=107954.112 memory=2 cpu=0.00%
[11/Jun/2020:16:12:22 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=55877.479 memory=2 cpu=0.02%
[11/Jun/2020:15:26:19 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=55912.678 memory=2 cpu=0.00%
[11/Jun/2020:15:36:33 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=54738.373 memory=2 cpu=0.02%

而且我有一个脚本可以按时间、内存和 cpu 进行排序,但只有在排序前删除静态字符串 time= 才能做到这一点。

cat /var/log/requests.log | sed -e "s/time=//" | sort -k 7 -n -r | head -50

我明白了

[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 137172.179 memory=2 cpu=0.01%
[11/Jun/2020:15:35:39 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 107954.112 memory=2 cpu=0.00%
[11/Jun/2020:14:59:03 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 106956.770 memory=2 cpu=0.01%
[11/Jun/2020:15:35:20 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 72161.647 memory=2 cpu=0.01%
[11/Jun/2020:15:22:13 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 70564.992 memory=2 cpu=0.00%
[11/Jun/2020:15:35:26 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 70252.369 memory=2 cpu=0.00%
[11/Jun/2020:15:31:35 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 68882.501 memory=2 cpu=0.03%
[11/Jun/2020:16:45:38 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 61264.044 memory=2 cpu=0.02%
[11/Jun/2020:15:01:02 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 60159.409 memory=2 cpu=0.03%
[11/Jun/2020:15:37:56 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 60014.014 memory=2 cpu=0.00%
[11/Jun/2020:15:01:48 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 58733.325 memory=2 cpu=0.02%
[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 57021.375 memory=2 cpu=0.00%
[11/Jun/2020:15:26:19 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 55912.678 memory=2 cpu=0.00%
[11/Jun/2020:16:12:22 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 55877.479 memory=2 cpu=0.02%
[11/Jun/2020:15:47:01 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX 55443.752 memory=2 cpu=0.02%

我想在不删除排序键的情况下对列表进行排序。

[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=137172.179 memory=2 cpu=0.01%
[11/Jun/2020:15:35:39 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=107954.112 memory=2 cpu=0.00%
[11/Jun/2020:14:59:03 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=106956.770 memory=2 cpu=0.01%
[11/Jun/2020:15:35:20 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=72161.647 memory=2 cpu=0.01%
[11/Jun/2020:15:22:13 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=70564.992 memory=2 cpu=0.00%
[11/Jun/2020:15:35:26 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=70252.369 memory=2 cpu=0.00%
[11/Jun/2020:15:31:35 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=68882.501 memory=2 cpu=0.03%
[11/Jun/2020:16:45:38 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=61264.044 memory=2 cpu=0.02%
[11/Jun/2020:15:01:02 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=60159.409 memory=2 cpu=0.03%
[11/Jun/2020:15:37:56 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=60014.014 memory=2 cpu=0.00%
[11/Jun/2020:15:01:48 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=58733.325 memory=2 cpu=0.02%
[11/Jun/2020:14:59:46 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=57021.375 memory=2 cpu=0.00%
[11/Jun/2020:15:26:19 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=55912.678 memory=2 cpu=0.00%
[11/Jun/2020:16:12:22 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=55877.479 memory=2 cpu=0.02%
[11/Jun/2020:15:47:01 +0000] 200 GET /endpoint ip=XXX.XXX.XXX.XXX time=55443.752 memory=2 cpu=0.02%

我试过了,但没有成功:

cat /var/log/requests.log | sort -k 7.6 -n -r | head -50

更新:/endpoint 是真正的端点,那么它们可以包含查询字符串。 更新 2:我需要对任何 key=value 列(作为数字)进行排序。

【问题讨论】:

    标签: bash sorting awk


    【解决方案1】:

    如果您的输入具有适当的代表性,您可以简单地使用= 作为列分隔符。

    sort -t = -k3 -k4 -k5 -n -r /var/log/requests.log
    

    还要注意我们如何避免useless cat.

    更一般地说,您可以使用简单的 Awk 脚本来提取排序字段并将它们放在首位,然后对它们进行排序,然后丢弃它们(称为 Schwartzian transform)。

    awk '{ for(i=1; i<=NF; ++i) if ($i ~ /^(time|memory|cpu)=/) {
            split($i, f, "="); a[f[1]] = substr($i, length(f[1])+2) }
        print a["time"] "\t" a["memory"] "\t" a["cpu"] "\t" $0 }' /var/log/requests.log |
    sort -r -n |
    cut -f4-
    

    if 语句提取包含我们感兴趣的前缀的任何字段(如果您愿意,可以在此处添加更多键,或者如果您想提取包含等号的所有内容,请切换到更通用的正则表达式例如,在一系列字母之后)并用它们各自的值填充关联数组a。一旦我们遍历了所有字段,我们就可以按照我们希望用于排序的顺序从数组中提取值。

    演示:https://ideone.com/dU9v95

    【讨论】:

    • 这不会改变它们(就像对它们进行排序一样)。它添加排序前缀、排序和删除排序前缀,精确地让您返回与输入完全相同的行。
    • 尝试if ($i ~ /^[a-z]+=/) 提取任何字母数字字段。 print 仍然需要包含您要排序的字段的枚举,因为它不知道您希望它们按哪个顺序排列。
    • 不要将命令放在变量中; mywiki.wooledge.org/BashFAQ/050
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 2018-10-27
    • 2015-06-30
    • 2012-07-23
    • 2019-12-30
    • 2011-01-16
    • 1970-01-01
    相关资源
    最近更新 更多