关于shell:使用awk调用可执行程序

Calling an executable program using awk

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


从awk手册页:

1
2
system(cmd)
              executes cmd and returns its exit status

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

1
system("date | mail -s 'awk run done' root")


有几种方法。

  • awk有一个system()函数,它将运行shell命令:

    system("cmd")

  • 可以打印到管道:

    print"blah" |"cmd"

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

    awk 'some script' | sh


  • 像这样简单的事情就行了

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

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


    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/awk -f

    BEGIN {
        command ="ls -lh"

        command |getline
    }

    在awk脚本中运行"ls-lh"


    这真的取决于:)一个方便的Linux核心实用程序(info coreutilsxargs。如果您使用的是awk,那么您可能会想到一个更复杂的用例——您的问题并不是很详细。

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

    将执行touch 2 4。在这里,你的程序可以取代touch。更多信息请访问info xargsman xargs(真的,请阅读这些)。我相信你会用你的程序来取代touch

    前面提到的脚本分解:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    printf"1 2
    3 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
    3 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
    3 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是更好、更易于携带的替代方案(在这里可以找到与讨论的巨大联系)。


    一种更健壮的方法是使用GNU awkgetline()函数使用管道中的变量。从cmd | getline结果来看,cmd运行,其输出通过管道输送到getline上。如果得到输出,返回1;如果eof,返回0;失败,返回-1

    如果命令不依赖于文件的内容,例如简单的datels,则首先构造在BEGIN子句中的变量中运行的命令。

    上面的一个简单例子是

    1
    2
    3
    4
    5
    6
    7
    awk 'BEGIN {
        cmd ="ls -lrth"
        while ( ( cmd | getline result ) > 0 ) {
            print result
        }
        close(cmd);
    }'

    当要运行的命令是文件的列内容的一部分时,您将在主{..}中生成cmd字符串,如下所示。例如,考虑一个文件,其$2包含文件名,您希望用该文件的md5sum哈希内容替换该文件。你可以做到

    1
    2
    3
    4
    5
    6
    awk '{ cmd ="md5sum"$2
           while ( ( cmd | getline md5result ) > 0 ) {
               $2 = md5result
           }
           close(cmd);
     }1'


    我可以通过下面的方法完成这项工作

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

    awk有一个名为system的函数,它允许您在awk的输出中执行任何Linuxbash命令。


    我用awk的力量删除了一些我停止的码头集装箱。在传递给system之前,请仔细观察我是如何构造cmd字符串的。

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

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