【问题标题】:Compare multiple Columns and Append the result into another file比较多个列并将结果附加到另一个文件中
【发布时间】:2015-01-20 10:09:33
【问题描述】:

我有两个文件file1file2,这两个文件都有5 columns。 我想将file1 中的first 4 columnsfile2 进行比较。

如果相等,需要比较5th column。如果5th column values不同,需要将file1's 5th column打印为file2's 6th column

我使用下面的awk 来比较两个不同文件中的两列,但是如果找到匹配项,如何比较多个列并将特定列附加到另一个文件中?

awk -F, 'NR==FNR{_1[$1]++;next}!_1[$1]'

文件1:

111,item1,garde1,wing1,maingroup
123,item3,grade5,wing10,topcat
132,item2,grade3,wing7,middlecat
134,item2,grade3,wing7,middlecat
177,item8,gradeA,wing11,lowcat

文件2:

111,item1,garde1,wing1,maingroup
123,item3,grade5,wing10,lowcat
132,item3,grade3,wing7,middlecat
126,item2,grade3,wing7,maingroup
177,item8,gradeA,wing11,lowcat

期望的输出:

123,item3,grade5,wing10,lowcat,topcat

【问题讨论】:

  • 在编写软件时,通常认为给变量起有意义的名称是个好主意。 _1 不符合条件!

标签: shell unix awk


【解决方案1】:

Awk 可以通过对索引进行排序来模拟多维数组。下面的索引使用内置的 SUBSEP 变量作为分隔符连接:

 $ awk -F, -v OFS=, 'NR==FNR { a[$1,$2,$3,$4]=$5; next } a[$1,$2,$3,$4] && a[$1,$2,$3,$4] != $5 { print $0,a[$1,$2,$3,$4] }' file1.txt file2.txt

123,item3,grade5,wing10,lowcat,topcat

awk -F, -v OFS=,

将输入和输出分隔符都设置为,

NR==FNR { a[$1,$2,$3,$4]=$5; next }

从第一个文件创建一个关联数组,将每行的前四个字段与 第五。当使用逗号分隔的值列表作为索引时,awk 实际上将它们连接起来 使用内置 SUBSEP 变量的值作为分隔符。这是awk的方式 用单个下标模拟多维数组。您可以将 SUBSEP 设置为您喜欢的任何值 但默认值,即不太可能出现在数据中的非打印字符,通常是 美好的。 (你也可以自己动手,比如a[$1 "|" $2 "|" $3 "|" $4], 假设您知道您的数据不包含竖线。)

a[$1,$2,$3,$4] && a[$1,$2,$3,$4] != $5 { print $0,a[$1,$2,$3,$4] }

到达这里,我们知道我们正在查看第二个文件。如果前四个字段在 第一个文件,并且第一个文件中的 $5 与第二个文件中的 $5 不同,打印该行 来自第二个文件,然后是第一个文件中的 $5。 (我在这里假设第一个文件中的 $5 不会具有评估为 false 的值,例如 0 或空。)

【讨论】:

  • 你能解释一下吗?
  • 您可以通过使用变量来存储字段使其更短且更具可读性,下一个是多余的awk -F, '{x=$1 $2 $3 $4}NR==FNR{a[x]=$5}a[x]&&a[x]!=$5{print $0,a[x]}'
  • 当然,@Marjer,请参阅编辑以了解其他 cmets。
  • 如果第 5 个字段包含一个计算结果为零或为空的值,这将失败。
  • 没错,@EdMorton,我在扩展的 cmets 中确实提到了这一点。这个问题似乎没问题,但同意将代码放在那里做出这样的假设是一个坏主意(而且我很懒)。
【解决方案2】:
$ cat tst.awk
BEGIN { FS=OFS="," }
{ key = $0; sub("(,[^,]*){"NF-4"}$","",key) }
NR==FNR { file1[key] = $5; next }
(key in file1) && ($5 != file1[key]) {
    print $0, file1[key]
}

$ awk -f tst.awk file1 file2
123,item3,grade5,wing10,lowcat,topcat

【讨论】:

    猜你喜欢
    • 2014-05-27
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2021-12-01
    相关资源
    最近更新 更多