我有一个 C 语言程序,我想在 shell 脚本中使用 awk 来调用它。我怎么能做这样的事情?
8 回答
一种更健壮的方法是使用getline()
GNU 的函数awk
来使用管道中的变量。在表单cmd | getline
结果中,cmd
运行,然后将其输出通过管道传输到getline
. 1
如果有输出,0
如果 EOF,-1
失败时返回。
BEGIN
如果命令不依赖于文件的内容,例如简单date
或ls
.
上面的一个简单例子是
awk 'BEGIN {
cmd = "ls -lrth"
while ( ( cmd | getline result ) > 0 ) {
print result
}
close(cmd);
}'
当要运行的命令是文件的列内容的一部分时,您会cmd
在 main 中生成字符串,{..}
如下所示。例如,考虑一个$2
包含文件名的文件,并且您希望将其替换为md5sum
文件的哈希内容。你可以做
awk '{ cmd = "md5sum "$2
while ( ( cmd | getline md5result ) > 0 ) {
$2 = md5result
}
close(cmd);
}1'
涉及外部命令的另一个常见用法awk
是在date
处理期间,当您awk
不支持开箱即用的时间函数时mktime()
,strftime()
函数。
考虑一种情况,当您将 Unix EPOCH 时间戳存储在列中并且您希望将其转换为人类可读的日期格式。假设 GNUdate
可用
awk '{ cmd = "date -d @" $1 " +\"%d-%m-%Y %H:%M:%S\""
while ( ( cmd | getline fmtDate) > 0 ) {
$1 = fmtDate
}
close(cmd);
}1'
对于输入字符串
1572608319 foo bar zoo
上面的命令产生的输出为
01-11-2019 07:38:39 foo bar zoo
可以定制该命令以修改date
给定行中任何列上的字段。请注意,这-d
是一个 GNU 特定的扩展,*BSD 变体支持-f
(虽然不完全相似-d
)。
有关更多信息,请参阅 awk.freeshell.org页面上getline
的这篇AllAboutGetline文章。
有几种方法。
awk 有一个
system()
可以运行 shell 命令的函数:system("cmd")
您可以打印到管道:
print "blah" | "cmd"
您可以使用 awk 构造命令,并将所有输出通过管道传输到 shell:
awk 'some script' | sh
像这样简单的东西会起作用
awk 'BEGIN{system("echo hello")}'
和
awk 'BEGIN { system("date"); close("date")}'
这真的取决于 :) 方便的 linux 核心 utils ( info coreutils
) 之一是xargs
. 如果您正在使用awk
,您可能会想到一个更复杂的用例 - 您的问题不是很详细。
printf "1 2\n3 4" | awk '{ print $2 }' | xargs touch
将执行touch 2 4
。这里touch
可以替换为您的程序。更多信息info xargs
和man xargs
(真的,阅读这些)。我相信你想touch
用你的程序替换。
前面提到的脚本的细分:
printf "1 2\n3 4"
# Output:
1 2
3 4
# The pipe (|) makes the output of the left command the input of
# the right command (simplified)
printf "1 2\n3 4" | awk '{ print $2 }'
# Output (of the awk command):
2
4
# xargs will execute a command with arguments. The arguments
# are made up taking the input to xargs (in this case the output
# of the awk command, which is "2 4".
printf "1 2\n3 4" | awk '{ print $2 }' | xargs touch
# No output, but executes: `touch 2 4` which will create (or update
# timestamp if the files already exist) files with the name "2" and "4"
更新在原始答案中,我使用echo
而不是printf
. 但是,printf
正如评论所指出的那样,这是更好、更便携的替代方案(可以找到与讨论的重要链接)。
我使用 awk 的强大功能删除了一些已停止的 docker 容器。在将cmd
字符串传递给system
.
docker ps -a | awk '$3 ~ "/bin/clish" { cmd="docker rm "$1;system(cmd)}'
在这里,我使用模式为“/bin/clish”的第三列,然后在第一列中提取容器 ID 来构造我的cmd
字符串并将其传递给system
.
#!/usr/bin/awk -f
BEGIN {
command = "ls -lh"
command |getline
}
在 awk 脚本中运行“ls -lh”
我能够通过以下方法完成此操作
cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk '{system(`date`); print $1}'
awk 有一个名为 system 的函数,它使您能够在 awk 的输出中执行任何 linux bash 命令。