为什么我的脚本会出现此错误?awk:script.awk:19:“语法错误

为什么我的脚本会出现此错误?awk:script.awk:19:“语法错误

我有 2 个文本文件

1.txt

AA;00000;
BB;11111;
GG;22222;

2.txt

KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;

我尝试生成以下3.txt输出:

AA;00000;
BB;11111;KK;WW;55555;KK;FF;ZZ;KK;RR;YY;
GG;22222;

删除重复字段后我应该有这个

AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;

简单来说:在两个以;(FS=";") 分隔的文件中,如果文件 1 中的字段$n出现在$m文件 2 中的任何位置,且 m,n 不为 1,则将其附加$0(file2,m)$0(file1,n)。必须避免出现重复的字段。

我会尝试勾勒出一个解决方案

awk -f script.awk 2.txt 1.txt

其中脚本如下:

BEGIN {
    FS=";"
    OFS=";"
}

NR==FNR {
    allRecordsFile2[i++] = $0;
    next;
}

{
    for(r in allRecordsFile2)
    {
         split(allRecordsFile2[r],";",array)
         for(f in array)
         {
             for($2 through $n of file1 currently processed)
             {
                 if $n == f --> $0 = $0";"allRecordsFile2[r]
             }
         }
    }

    ## cleanup duplicates

    print $0
}

我仍然需要努力清除重复项,但可能可以通过拆分$0";"使用计数数组来跟踪重复项来完成。

但是运行这个脚本后我返回语法错误

C:\Program Files (x86)\GnuWin32\bin>awk -f script.awk file2.txt file1.txt

awk: script.awk:17: for($2 through $n of filei currently processed)
awk: script.awk:17: “ syntax error
awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r]
awk: script.awk:19: “ syntax error
awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r]
awk: script.awk:19: “ syntax error
errcount:3

语法错误

答案1

与其尝试顺序读取并基于FNR/进行控制NR,为什么不使用getline读取2.txt并拆分';',然后构建输出字符串(o如下)来连接每行中唯一的组件?您可以做类似的事情:

awk '{
        printf "%s", $0
    }
    /^BB/ {
        o = ""
        while (getline tmp < "2.txt") {
            n = split (tmp,arr,";")
            for (i=1; i<=n; i++)
                if(!match($0,arr[i]) && !match(o,arr[i]))
                    o=o arr[i]";"
        }
        printf "%s", o
    }
    {
        print ""
    }
' 1.txt

使用/输出示例

1.txt使用和中的示例数据2.txt(您1.txt再次错误命名),您将收到:

$ awk '{
>         printf "%s", $0
>     }
>     /^BB/ {
>         o = ""
>         while (getline tmp < "2.txt") {
>             n = split (tmp,arr,";")
>             for (i=1; i<=n; i++)
>                 if(!match($0,arr[i]) && !match(o,arr[i]))
>                     o=o arr[i]";"
>         }
>         printf "%s", o
>     }
>     {
>         print ""
>     }
> ' 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;

这看上去就像你想要的。


作为以两个文件名作为参数的脚本

Windows 应该遵循相同的约定ARGV。请注意,在脚本中运行时,不要在规则周围加上单引号awk,例如

#!/usr/bin/awk -f 

NR != FNR {
    exit
}
{
    printf "%s", $0
}
/^BB/ {
    o = ""
    while (getline tmp < ARGV[2]) {
        n = split (tmp,arr,";")
        for (i=1; i<=n; i++)
            if(!match($0,arr[i]) && !match(o,arr[i]))
                o=o arr[i]";"
    }
    printf "%s", o
}
{
    print ""
}

笔记:您需要将/usr/bin/awk解释器更改为您拥有的任何解释器)

用法是,例如./test.awk 1.txt 2.txt

如果有帮助的话请告诉我。

答案2

使用关联数组的键可以方便地处理重复项。这需要 GNU awk 来实现多维数组

BEGIN { FS = OFS = ";" }
NR == FNR {
    for (i=1; i<NF-1; i++)
        f2[$(NF-1)][$i] = ++n
    next
}
FNR == 1 {
    # this joins all the 2nd-level indices
    # the order of them is undefined.
    for (x in f2) {
        s = ""
        for (y in f2[x])
            s = s y OFS
        a[x] = s
    }
}
$(NF - 1) in a { $NF = a[$(NF-1)] }
1

然后

gawk -f script.awk {2,1}.txt

生产

AA;00000;
BB;11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;22222;

我需要更多证据证明它对 URL“不起作用”:

$ cat 1.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;
GG;http://a.o/f/i.p?t=22222;

$ cat 2.txt
KK;WW;55555;http://a.o/f/i.p?t=11111;
KK;FF;ZZ;http://a.o/f/i.p?t=11111;
KK;RR;YY;http://a.o/f/i.p?t=11111;

$ gawk -f script.awk {2,1}.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;http://a.o/f/i.p?t=22222;

相关内容