【问题标题】:Print a variable column using awk使用 awk 打印变量列
【发布时间】:2018-08-30 12:54:14
【问题描述】:

我正在尝试过滤一些邮件日志,我需要从某些不总是相同的列中获取一些特定信息。信息可以在每行的不同列上。我总是使用 awk 只打印我想要的列,例如:

cat file.log | awk '{print $1" "$2" "$3}' >> output.txt

但在这种情况下,我不知道哪一列包含我要查找的字符串。

我在其中查找包含字符串“5”的列的示例 file.log:

A B C 222 586 999 724 644  
A B C 510 333 987 678 633  
A B C 348 488 920 566 240  

我想要的结果:

A B C 586  
A B C 510  
A B C 566  

感谢任何帮助

【问题讨论】:

  • 如果你可以考虑perl,那么你可以考虑$perl -pe "s/^(\D+).*\b(5\d*).*/$1$2/" your_file.txt

标签: logging awk


【解决方案1】:

使用~ /5/ 并在每行/行的每列上迭代 (KISS):

$ awk '
    {
        for (i=1; i<=NF; i++) {
            if (i==1 || i==2 || i==3 || $i ~ /5/) {
                printf "%s ", $i
            }
         }
         print ""
    }
' file

输出:

A B C 586 
A B C 510 
A B C 566 

【讨论】:

    【解决方案2】:

    一个棘手的 perl 单行代码

    perl -anE 'say "@{[ @F[0..2], grep {/5/} @F[3..$#F] ]}"' file
    

    在哪里

    • -n 逐行遍历输入文件
    • -a 将每一行拆分为单词,并存储到@F 数组中
    • @F[0..2] 是前三个字; @F[3..$#F] 是最后一个单词的第 4 个列表
    • grep {/5/} 过滤列表,只返回包含“5”的单词
    • "@{[ ... ]}" 是一种将列表字符串化为空格分隔的语法技巧。

    也可以使用这个,同样棘手但少了一点“syntax-y”

    perl -anE 'push @F, grep {/5/} splice @F,3; say "@F"'
    

    【讨论】:

    • 我猜perl -pe "s/^(\D+).*\b(5\d*).*/$1$2/" 会完成这项工作
    • perl -ape "s/\d.*//s;$_=$_. join(' ', grep{/5/} @F).\"\n\"" file
    【解决方案3】:
    $ awk '{
        for(i=4;i<=NF;i++)    # iterate fields starting from the 4th
            if($i~/5/)        # if there is a 5 in the field
                $3=$3 OFS $i  # append field value to the 3rd field
        print $1,$2,$3        # output 1st thru 3rd
    }' file
    
    Output:
    
    A B C 586
    A B C 510
    A B C 566
    

    【讨论】:

    • 也许是OFS 而不是" "
    猜你喜欢
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2014-05-13
    • 2010-12-22
    相关资源
    最近更新 更多