将系统命令的输出分配给变量

时间:2009-12-25 09:53:13

标签: awk pipe

我想在awk脚本中运行system命令并将其输出存储在变量中。我一直试图这样做,但命令的输出总是进入shell而我无法捕获它。关于如何做到这一点的任何想法?

示例:

$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/}

应调用strip系统命令而不是将输出发送到shell,应将输出分配回$1以进行更多处理。现在Rignt,它将输出发送到shell并将命令的重新编码分配给$1

6 个答案:

答案 0 :(得分:55)

注意:Coprocess特定于GNU awk。 无论如何另一种选择是使用getline

cmd = "strip "$1
while ( ( cmd | getline result ) > 0 ) {
  print  result
} 
close(cmd)

调用close(cmd)会阻止awk在多次调用后抛出此错误:

  

致命:无法打开管道`...'(打开的文件过多)

答案 1 :(得分:27)

想通了。

我们使用awk的Two-way I/O

{
  "strip $1" |& getline $1
}

将$ 1传递给strip,getline将条带的输出返回到$ 1

答案 2 :(得分:26)

要在awk中运行系统命令,您可以使用system()cmd | getline

我更喜欢cmd | getline,因为它允许您将值捕获到变量中:

$ awk 'BEGIN {"date" |  getline mydate; close("date"); print "returns", mydate}'
returns Thu Jul 28 10:16:55 CEST 2016

更一般地说,您可以将命令设置为变量:

awk 'BEGIN {
       cmd = "date -j -f %s"
       cmd | getline mydate
       close(cmd)
     }'

请注意,使用close()来阻止获取太多打开的文件非常重要"如果您有多个结果会出错(感谢mateuscb在评论中指出这一点)。

使用system(),自动打印命令输出,您可以捕获的值是其返回码:

$ awk 'BEGIN {d=system("date"); print "returns", d}'
Thu Jul 28 10:16:12 CEST 2016
returns 0
$ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}'
ls: cannot access asdfasdfasd: No such file or directory
returns 2

答案 3 :(得分:6)

gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}'

答案 4 :(得分:2)

需要处理grep输出时的有用示例:

echo "some/path/exex.c:some text" | awk -F: '{ "basename "$1"" |& getline $1; print $1 " ==> " $2}'

-F:使用:作为字段分隔符

"basename "$1""使用第一个字段执行shell命令

|& getline $1读取子流

中shell命令的输出
output:
exex.c ==> some text

答案 5 :(得分:1)

我正在使用macOS的awk,并且我还需要该命令的退出状态。因此,我扩展了@ ghostdog74的解决方案以获取退出状态:

如果退出状态为非零,则退出:

cmd = <your command goes here>
cmd = cmd" ; printf \"\n$?\""

last_res = ""
value = ""        

while ( ( cmd | getline res ) > 0 ) {

    if (value == "") {
        value = last_res
    } else {
        value = value"\n"last_res
    }

    last_res = res
}

close(cmd)

# Now `res` has the exit status of the command
# and `value` has the complete output of command

if (res != 0) {
    exit 1
} else {
    print value
}

因此,基本上我只是更改了cmd以在新行上打印命令的退出状态。执行上述while循环后,res将包含命令的退出状态,并且 value将包含命令的完整输出。

老实说,这不是一种很整洁的方法,我自己想知道是否还有更好的方法。