【问题标题】:Unix - Print Common Lines side by sideUnix - 并排打印公共行
【发布时间】:2016-05-31 16:19:34
【问题描述】:

我想比较 2 个未排序的文件并并排打印公共行

文件1

一个 1 2
b 2 4
c 1 4
e 1 2

文件2
0 3
c 1 4
d 3 4
b 2 4

输出1

1 2 0 3
b 2 4 2 4
c 1 4 1 4

输出2
1 2 0 3
b 2 4 2 4
c 1 4 1 4
d 3 4
e 1 2

我可以使用 Join 实现,但我想使用 awk 查找命令。

我们可以不对文件进行排序并使用awk来获取output1和output2吗?

【问题讨论】:

    标签: unix awk


    【解决方案1】:
    $ awk '
        NR==FNR {line[$1]=$0; next} 
        $1 in line {
            f2fields = gensub($1 FS, "", 1)
            print line[$1], f2fields > "output1"
            print line[$1], f2fields > "output2"
            seen[$1]++
            next
        } 
        {print > "output2"} 
        END { for (key in line) if (!(key in seen)) print line[key] > "output2" }
    ' file1 file2
    
    $ cat output1
    a 1 2 0 3
    c 1 4 1 4
    b 2 4 2 4
    
    $ cat output2
    a 1 2 0 3
    c 1 4 1 4
    d 3 4
    b 2 4 2 4
    e 1 2
    

    输出{1,2}文件的顺序由1)file2的记录顺序决定,然后2)file1中没有出现在file2中的记录被“随机”输出(以哈希顺序)。

    【讨论】:

    • 感谢您的回复。我尝试了该命令,但它对我有用。我修改了 f2fileds 并尝试了 output1 ,但是第二个文件是用键列打印的。您能否就如何仅从第二列中获取第二个文件提出建议? awk -F "," 'FNR==NR{a[$1]=$0;next} $1 in a{f2=$0; print a[$1],f2;next} ' file1 file2 > output1 $ cat output1 a 1 2 a 0 3 c 1 4 c 1 4 b 2 4 b 2 4
    【解决方案2】:

    你可以像这样使用 GNU awk 做到这一点:

    script.awk

    BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc" }
    
    FNR == NR { lines[$1] = $0; next }
    FNR != NR { if( $1 in lines ) {
                  k = $1
                  # strip unnecessary key $1 from $0
                  $1 = ""
                  lines[ k ] = lines[ k ] $0
                }
                else lines[$1] = $0;
              }
    
    END { for( k in lines ) print lines[ k ] }
    

    像这样使用它:awk -f script.awk file1 file2

    PROCINFO 对 gnu awk 来说是特殊的。如果你不需要排序并且没有gnu awk,你可以注释掉第一行,看看会发生什么。

    【讨论】:

    • 感谢您的回复。我尝试了该命令,但它对我有用。我修改了 f2fileds 并尝试了 output1 ,但是第二个文件是用键列打印的。您能否就如何仅从第二列中获取第二个文件提出建议? awk -F "," 'FNR==NR{a[$1]=$0;next} $1 in a{f2=$0; print a[$1],f2;next} ' file1 file2 > output1 $ cat output1 a 1 2 a 0 3 c 1 4 c 1 4 b 2 4 b 2 4
    • @Apama 删除文件 2 的密钥是在 FNR != NR 操作中通过设置 $1= "" 然后使用 $0 来完成的。至少在 GNU awk 中 $0 得到更新,之后由原始的 $2 ... $5 组成。如果这不起作用,请改用:lines[ k ] = lines[ k ] $2 $3 $4 $5。顺便说一句,您可以通过注释掉 else 部分来获得 output1。
    • @Apama 在您的第一条评论中使用 `awk -F ","`,这意味着逗号字段分隔符。问题中的示例以空格分隔,因此我不确定您是否需要-F "," 部分。
    • 非常感谢。由于测试的文件不同,这是错字。然而,FS dint 给我带来了这个问题。我能够解决从 $2 打印的问题。
    猜你喜欢
    • 2016-07-08
    • 2015-04-17
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多