65

我有一个 C 语言程序,我想在 shell 脚本中使用 awk 来调用它。我怎么能做这样的事情?

4

8 回答 8

58

从 AWK 手册页:

系统(cmd)
              执行 cmd 并返回其退出状态

GNU AWK手册还有一个部分,部分描述了该system功能并提供了一个示例:

system("date | mail -s 'awk run done' root")
于 2013-01-31T20:19:50.863 回答
33

一种更健壮的方法是使用getline()GNU 的函数awk来使用管道中的变量。在表单cmd | getline结果中,cmd运行,然后将其输出通过管道传输到getline. 1如果有输出,0如果 EOF,-1失败时返回。

BEGIN如果命令依赖于文件的内容,例如简单datels.

上面的一个简单例子是

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文章。

于 2019-03-21T10:54:23.240 回答
32

有几种方法。

  1. awk 有一个system()可以运行 shell 命令的函数:

    system("cmd")

  2. 您可以打印到管道:

    print "blah" | "cmd"

  3. 您可以使用 awk 构造命令,并将所有输出通过管道传输到 shell:

    awk 'some script' | sh

于 2013-01-31T20:22:53.733 回答
5

像这样简单的东西会起作用

awk 'BEGIN{system("echo hello")}'

awk 'BEGIN { system("date"); close("date")}'

于 2013-02-01T01:32:50.147 回答
4

这真的取决于 :) 方便的 linux 核心 utils ( info coreutils) 之一是xargs. 如果您正在使用awk,您可能会想到一个更复杂的用例 - 您的问题不是很详细。

printf "1 2\n3 4" | awk '{ print $2 }' | xargs touch

将执行touch 2 4。这里touch可以替换为您的程序。更多信息info xargsman 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正如评论所指出的那样,这是更好、更便携的替代方案(可以找到与讨论的重要链接)。

于 2016-04-30T16:31:58.867 回答
4

我使用 awk 的强大功能删除了一些已停止的 docker 容器。在将cmd字符串传递给system.

docker ps -a | awk '$3 ~ "/bin/clish" { cmd="docker rm "$1;system(cmd)}'

在这里,我使用模式为“/bin/clish”的第三列,然后在第一列中提取容器 ID 来构造我的cmd字符串并将其传递给system.

于 2018-01-10T07:31:09.573 回答
3
#!/usr/bin/awk -f

BEGIN {
    command = "ls -lh"

    command |getline
}

在 awk 脚本中运行“ls -lh”

于 2016-06-16T08:19:31.317 回答
0

我能够通过以下方法完成此操作

cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk '{system(`date`); print $1}'

awk 有一个名为 system 的函数,它使您能够在 awk 的输出中执行任何 linux bash 命令。

于 2018-01-15T11:35:22.957 回答