为什么 awk 打印重定向失败?

Why print of awk failed to redirect?

我需要将配置文件 1 合并到配置文件 2。如果文件 1 有文件 2 没有,则将其附加到文件 2 的末尾。我可以用系统替换打印以修复错误,但我不知道为什么打印不起作用。

使用print i"=" a[i] >> ARGV[2];,未能将文本追加到文本末尾

1.txt,注意第三行是空行:

key=5678
abc=000

  1. txt:
key=1234

test.awk:

#!/usr/bin/env -S gawk -F= -f
{
    key = gensub(/\s/, "", "g", );
    if (NR==FNR) {
        a[key]=;
    } else {
        b[key]=;
    }
}

END{
    for (i in a) {
        if (b[i] == "") {
            print "bi = empty, append to end of file:" i"="a[i];
            print i"="a[i] >> ARGV[2];
            # system("echo " i "=" a[i] ">>" ARGV[2]);
        } else if (a[i] != b[i]) {
            cmd = sprintf("sed -i -r 's@\s*(%s)\s*=.*@\1=%s@' %s", i, a[i], ARGV[2]);
            system(cmd);
        }
    }
}

运行 ./test.awk 1.txt 2.txt 结果:

$ ./test.awk 1.txt 2.txt 
bi = empty, append to end of file:=
bi = empty, append to end of file:abc=000
$ cat 2.txt 
key=5678
=

为什么 abc=000 没有添加到 2.txt?如果改成system("echo" i "=" a [i] ">" argv [2]),又OK了,是不是print有bug?

在gnu awk手册中,“5.9关闭输入和输出重定向”,需要调用close函数,当多个命令操作同一个文件时,例如pipe或cmd, 太糟糕了,所以我放弃打印>>,只使用system()。

最后,我使用这个脚本:

#!/usr/bin/env -S gawk -F"=|is" -f
# File:   sync_kernelconfig.awk
# Author: Edward.Tang
# Mail:   edaplayer@163.com
# Function: 同步文件1的内核配置到文件2

function set_value(array, comment, k, v)
{
    if (!/^\s*#/) {
        array[k]=v;
    } else {
        comment[k]=;
    }
}

{
    key = gensub(/#|\s/, "", "g", );

    if (key == "") next; # 跳过空行

    if (NR==FNR) {
        set_value(a1, c1, key, );
    } else {
        set_value(a2, c2, key, );
        line[key] = [=14=]; # line data of file2
    }
}

END {
    for (i in a1) {
        if (a2[i] == "") {
            if (c2[i] == "") {
                system("echo " i "=" a1[i] ">>" ARGV[2]);
            } else {
                cmd = sprintf("sed -i -r 's~%s~%s=%s~' %s", line[i], i, a1[i], ARGV[2]);
                system(cmd);
            }
        } else if (a1[i] != a2[i]) {
            cmd = sprintf("sed -i -r 's~%s~%s=%s~' %s", line[i], i, a1[i], ARGV[2]);
            system(cmd);
        }
    }

    for (i in c1) {
        if (a2[i] != "") {
            cmd = sprintf("sed -i -r 's~%s~# %s is%s~' %s", line[i], i, c1[i], ARGV[2]);
            system(cmd);
        }
    }
}

gnu awk手册中的“5.9关闭输入输出重定向”,需要调用close函数,当多个命令操作同一个文件时,比如pipe或cmd,就很糟糕了

所以我需要使用:

print i"="a[i] >> ARGV[2];
close(ARGV[2]);

或:

system("echo " i "=" a1[i] ">>" ARGV[2]);