我想在awk脚本中运行system
命令并将其输出存储在变量中。我一直试图这样做,但命令的输出总是进入shell而我无法捕获它。关于如何做到这一点的任何想法?
示例:
$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/}
应调用strip
系统命令而不是将输出发送到shell,应将输出分配回$1
以进行更多处理。现在Rignt,它将输出发送到shell并将命令的重新编码分配给$1
。
答案 0 :(得分:55)
注意:Coprocess特定于GNU awk。 无论如何另一种选择是使用getline
cmd = "strip "$1
while ( ( cmd | getline result ) > 0 ) {
print result
}
close(cmd)
调用close(cmd)
会阻止awk
在多次调用后抛出此错误:
致命:无法打开管道`...'(打开的文件过多)
答案 1 :(得分:27)
答案 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
读取子流
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
将包含命令的完整输出。
老实说,这不是一种很整洁的方法,我自己想知道是否还有更好的方法。