【问题标题】:Use AWK to print lines that have a certain string followed by a number greater than 10000使用 AWK 打印具有特定字符串后跟大于 10000 的数字的行
【发布时间】:2018-10-01 17:20:11
【问题描述】:

我有一个看起来像这样的文件:

column1 column2 column3 column4 column5 column6 Warn=3000
column1 column2 column3 column4 column5 Warn=200
column1 column2 column3 column4 column5 column6 column7 Warn=40000
column1 column2 column3 column4 Warn=100
column1 column2 column3 column4 column5 Warn=20000
column1 column2 column3 column4 Warn=15000

可以看出,每一行的字段数量都在变化,但最后一个字段总是“Warn=”后跟一个数字。 我基本上想打印“Warn =”字符串后面跟着一个大于10000的数字的所有行,并将它们从最高数字排序到最低数字。

所以结果应该是这样的:

column1 column2 column3 column4 column5 column6 column7 Warn=40000
column1 column2 column3 column4 column5 Warn=20000
column1 column2 column3 column4 column5 Warn=15000

到目前为止,通过使用 grep、awk 和 sort,我已经能够在一定程度上实现我想要的:

grep -E 'Warn=[0-9]{5}' file.txt | awk '{ print $NF, $0 }' | sort -rn -k1 | sed 's/Warn=[0-9]* //'

有没有更简单的方法来使用 awk?

【问题讨论】:

    标签: bash awk


    【解决方案1】:

    使用 GNU awk 进行 sorted_in:

    $ awk -F'=' -v OFS='\t' '$NF>10000{a[NR]=$NF; b[NR]=$0} END{PROCINFO["sorted_in"]="@val_num_desc"; for (i in a) print b[i]}' file
    column1 column2 column3 column4 column5 column6 column7 Warn=40000
    column1 column2 column3 column4 column5 Warn=20000
    column1 column2 column3 column4 Warn=15000
    

    或使用任何 awk 加上 sort + cut:

    $ awk -F'=' -v OFS='\t' '$NF>10000{print $NF, $0}' file | sort -nr | cut -f2-
    column1 column2 column3 column4 column5 column6 column7 Warn=40000
    column1 column2 column3 column4 column5 Warn=20000
    column1 column2 column3 column4 Warn=15000
    

    【讨论】:

    • 您可能需要将$(NF-1) ~ /Warn$/ && 添加到条件中以满足“警告”要求。
    • 我喜欢你使用 a 数组来允许多行具有重复的键值。
    • @glennjackman OP 说 the number of fields is changing on each line, but **the last field is always "Warn="** followed by a number 所以没有必要匹配 /Warn/,OP 只是在 Warn 为 5 位数字后测试数字以满足他的 1000+ 标准。谢谢!
    • 确实如此。谢谢你,埃德!
    【解决方案2】:

    编辑:既然 OP 提到 Input_file 也可以有 = 用于其他字段,那么请您尝试关注。

    awk '{split($NF,array,"=")} array[1]=="Warn" && array[2]>10000' Input_file | sort -t'=' -k2rn
    

    您能否尝试以下操作(考虑到实际的 Input_file 与显示的示例相同)。

    awk -F' |=' '$(NF-1)=="Warn" && $NF>10000'  Input_file
    

    OR 使用值排序:

    awk -F' |=' '$(NF-1)=="Warn" && $NF>10000' Input_file | sort -t'=' -k2rn
    

    输出如下。

    column1 column2 column3 column4 column5 column6 column7 Warn=40000
    column1 column2 column3 column4 column5 Warn=20000
    column1 column2 column3 column4 Warn=15000
    

    【讨论】:

    • 使用=作为排序分隔符的好主意,只要其他列都不包含=
    • @EdMorton,当然先生,我已经添加了一个公平的警告来回答。
    • 好主意!不幸的是,这些列还包含随机字符,其中还可以有“=”符号。
    • @Andy,你能试试我的 EDIT 代码,如果对你有帮助,请告诉我?
    • 谢谢@RavinderSingh13,很遗憾它不起作用。
    【解决方案3】:

    使用 Perl 单行代码

    > cat warn.txt
    column1 column2 column3 column4 column5 column6 Warn=3000
    column1 column2 column3 column4 column5 Warn=200
    column1 column2 column3 column4 column5 column6 column7 Warn=40000
    column1 column2 column3 column4 Warn=100
    column1 column2 column3 column4 column5 Warn=20000
    column1 column2 column3 column4 Warn=15000
    
    > perl -ne ' { if(m/(\d+)$/s && $1 >  10000) { $warn{$1}=$_; } }  END { foreach $key(reverse sort keys %warn) { print "$warn{$key}" } } ' warn.txt
    column1 column2 column3 column4 column5 column6 column7 Warn=40000
    column1 column2 column3 column4 column5 Warn=20000
    column1 column2 column3 column4 Warn=15000
    
    >
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 2017-01-16
      • 2020-05-14
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多