【问题标题】:How to use awk to print columns in a loop?如何使用 awk 循环打印列?
【发布时间】:2023-03-12 09:31:01
【问题描述】:

我有一些命令的多列文本输出,并且想一次打印一列,例如:

#!/usr/bin/ksh

typeset -i i=0
while [[ $i -lt 5 ]]; do
  <command 1> |awk '{print $i}' |<command 2>
  i=$i+1
done

我知道$i 不是在 awk 中指定第 i 列的方法。这里的正确用法是什么?

说,command 1 的输出类似于:

"abc" "def" "ghi" "jkm"
"123" "456" "789" "0ab"
"erf" "fad" "dae" "kjh"

该值不一定是 3 个字符长。这里只是举例。

我想把第 1 列依次拿到第 4 列,供command 2 使用。

【问题讨论】:

    标签: shell awk ksh


    【解决方案1】:

    您对$i shell 变量和$i awk 中的 ith 字段感到困惑。您需要在使用-v 时将shell 变量的值传递给awk

    #!/bin/bash
    
    for i in {1..5}; do 
        <command1> | awk -v i="$i" '{print $i}' | <command2>
    done
    

    这将使command2 分别处理来自command1 输出的每一列。

    【讨论】:

    • 是的,如果 i 从 1 到 5 开始,它就可以工作。但是如果我使用原始的 while 循环,并从 0 到 4 迭代 i,并使用 awk -v i="$i+1" '{print $i}',它就坏了再次。这里有什么补救措施吗?
    • 请注意,$0awk 中有一个含义,但它表示“整个输入行”,而不是该行中的字段。如果您想要 awk 输出中的第 1-4 列,您可以提供值 1..4 作为i 的值,或者使用awk -v i=$i '{print $(i+1)}'。但是你写的循环会从 4 个字段中生成 5 组输出,这可能不是一个好主意。
    • @QiangXu 所以只需将shell变量$i初始化为1即可。
    【解决方案2】:

    我不会在你的问题中循环。因为,这将执行相同的命令 (command 1) n 次(在您的示例中为 12 次),仅用于提取值。如果command 1 很昂贵,您的脚本会很慢。即使它不贵,也不是好的做法,我们不应该那样做。

    我建议你只执行一次 cmd1,然后将它的输出转换成一个格式,这个格式很容易传递给 commnd2。例如:

    OUT1=$(command1||awk '{for (i=1;i<=4;i++)print $i}')
    

    这会将输出转换为一行中的每个列,例如:

    "abc"
    "def"
    "ghi"
    "jkm"
    "123"
    "456"
    "789"
    "0ab"
    "erf"
    "fad"
    "dae"
    "kjh"
    

    然后您可以使用循环或其他方式处理变量$OUT1

    也可以在 awk 中调用 command2。这取决于要求。如果你不想捕获 cmd2 的输出,你可以这样做:

    $(command1||awk '{for (i=1;i<=4;i++)system("command2 "$i)}')
    

    但同样,这取决于您的逻辑/要求。

    【讨论】:

    • 很棒的建议!是的,这种新设计将极大地提高性能。非常感谢!
    • 仍然对一件事感到困惑,为什么print $i 会在一行中打印第 i 列,而不是打印整个第 i 列?
    • 有没有办法将awk逐列输出,然后在每一列上调用command 2(在for循环的帮助下)?比如我想先得到"abc"\n"123"\n"erf,把它用于command 2的输入。之后,将command 2"def"\n"456"\n"fad" 一起输入,依此类推。
    • 是的,cutawk '{print $x} x 是列的索引。您可以将 cmd1 的输出保存到O1,然后在O1 上应用该命令以获取该列。
    • 试图得到这样的输出,但徒劳无功。肯特,你能给我举个例子吗?这里的要求是command 1只执行一次,并逐列打印其输出。
    猜你喜欢
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    相关资源
    最近更新 更多