AWK:使用 'system(external programm)' 替换将文本附加到特定行

AWK: append text to specific line with 'system(external programm)' substitution

我有一个名为 data 的文件,如下所示:

orange
apple
pair
mango
grape

通过使用 awk -i inplace '{if (NR==4) [=17=]=[=17=]" is sweet"}{print}' data,我得到:

orange
apple
pair
mango is sweet
grape

我正在尝试通过 system() 获得相同的结果,但我不知道如何实现。

echo is sweet | xclip

xclip -o 输出 is sweet。我在努力

awk -i inplace '{if (NR==4) [=14=]=[=14=](system("xclip -o"))}{print}' data

cat -n data给我

     1  orange
     2  apple
     3  pair
     4  is sweet
     5  mango0
     6  grape

芒果和葡萄被推到下一行,is sweet 在第 4 行是独立的,mango 最后有一个 0

我如何更改命令,并且仍然使用 system("xclip -o") 以便第 4 行显示 mango is sweet,没有任何附加的 0 也没有额外的行,即与第一个示例一样?

我是 awk 的新手,如有任何帮助,我们将不胜感激。

system("foo") 只是调用一个程序 foo 和 returns foos 退出状态(即 0 表示成功,非- 失败为零)。您想要的东西可以捕获 foooutput(即 foo 写入标准输出的文本),而不是 exit status,所以调用system()是错误的做法。您在问题中看到的是 xclip -o 的输出与 awk 脚本的输出混合在一起。

这是做你想做的事情的方法(使用 date 而不是 xclip 因为这是每个人都可用的命令):

$ awk '
    NR==4 {
        cmd = "date +%F"
        [=10=] = [=10=] " " ( (cmd | getline line) > 0 ? line : "N/A" )
        close(cmd)
    }
    { print }
 ' file
orange
apple
pair
mango 2021-09-06
grape

请参阅 https://www.gnu.org/software/gawk/manual/gawk.html#Getline_002fVariable_002fPipe for more information on the above and make sure to read http://awk.freeshell.org/AllAboutGetline 了解为什么我要在使用它的输出之前测试 getline 的退出状态,以及为什么它不是在许多情况下使用的东西(但这个是合适的)。

作为“单线”,上面的内容是:

awk 'NR==4 { cmd = "date +%F"; [=11=] = [=11=] " " ( (cmd | getline line) > 0 ? line : "N/A" ); close(cmd) } { print }' file

万一它有用,这里有一个函数,它对 awk 的作用相当于 shell:

的命令替换
$ cat cmdsub.awk
function cmdsub(cmd,    line, n, out, cmd_stat, gl_stat) {
    ERRNO = ""
    while ( ( gl_stat=(cmd | getline line) ) > 0 ) {
        out = (n++ ? out ORS : "") line
    }
    cmd_stat = close(cmd)

    # If the above pipeline loop succeeded then all 3 error/status
    # variables will be 0 but if the above pipeline loop failed then
    #
    #    a) if cmd failed then
    #           i) ERRNO will be null
    #          ii) gl_stat will be 0 if 1st iteration, 1 otherwise.
    #         iii) cmd_stat will be non-zero if GNU awk,
    #                   poorly defined for POSIX awk so YMMV.
    #
    #    b) if cmd succeeded and getline failed then
    #           i) ERRNO will be non-null if GNU awk, null otherwise.
    #          ii) gl_stat will be less than zero
    #         iii) cmd_stat will be 0

    if ( (ERRNO == "") && ( (gl_stat != 0) || (cmd_stat != 0) ) ) {
        ERRNO = sprintf("CMD_STAT: %d, GL_STAT: %d", cmd_stat, gl_stat)
    }

    return out
}
BEGIN {
    print "foo", cmdsub("date +%F"), "bar"
    print (ERRNO ? "Failure: " ERRNO : "Success")
    exit (ERRNO ? 1 : 0)
}

$ awk -f cmdsub.awk
foo 2021-09-06 bar
Success

$ echo $?
0

它使用一个名为 ERRNO 的全局变量,与 gawk 已经用于 getline 失败的变量相同(注意:尽管它是名称,ERRNO 是一个字符串,而不是数字),并且依赖于close(cmd)cmd 失败时返回失败退出状态,这在 gawk 中发生,但在其他 awks YMMV 中发生,因为 POSIX 标准在这一点上是模糊的。

有关 ERRNOclose() 的更多信息,请参阅: