从与shell脚本中的第二个文件匹配前2个字段的文件中删除行

时间:2015-07-15 01:09:25

标签: linux bash shell

假设我有setA.txt

a|b|0.1
c|d|0.2
b|a|0.3

我也有setB.txt

c|d|200
a|b|100

现在我要从setA.txt行中删除与setB.txt具有相同前两个字段的行,因此输出应为:

b|a|0.3

我试过了:

comm -23 <(sort setA.txt) <(sort setB.txt)

但是相等是为整行定义的,所以它不起作用。我怎么能这样做?

3 个答案:

答案 0 :(得分:3)

$ awk -F\| 'FNR==NR{seen[$1,$2]=1;next;} !seen[$1,$2]' setB.txt setA.txt
b|a|0.3

这只读取setB.txt一次,从中提取所需信息,然后在决定要打印的行时读取setA.txt

如何运作

  • -F\|

    这会将字段分隔符设置为垂直条|

  • FNR==NR{seen[$1,$2]=1;next;}

    FNR是到目前为止从当前文件读取的行数,NR是读取的总行数。因此,当FNR==NR时,我们正在阅读第一个文件setB.txt。如果是这样,请将关联数组seen的值设置为true,1,用于由字段1和字段2组成的键。最后,跳过其余命令并从next行重新开始。

  • !seen[$1,$2]

    如果我们接到这个命令,我们正在处理第二个文件setA.txt。由于!表示否定,如果seen[$1,$2]为假,则条件为真,这意味着字段1和2的这种组合不在setB.txt中。如果是,则执行默认操作,即打印该行。

答案 1 :(得分:2)

这应该有效:

If objRange.Cells(intRow, 1) = Nothing Then

End If

这是如何运作的:

sed -n 's#\(^[^|]*|[^|]*\)|.*#/^\1/d#p' setB.txt |sed -f- setA.txt

生成输出:

sed -n 's#\(^[^|]*|[^|]*\)|.*#/^\1/d#p'

然后用作管道和输出后的下一个/^c|d/d /^a|b/d 的{​​{1}}脚本:

sed

答案 2 :(得分:0)

(IFS=$'|'; cat setA.txt | while read x y z; do grep -q -P "\Q$x|$y|\E" setB.txt || echo "$x|$y|$z"; done; )

解释:grep -q表示只测试grep是否可以找到正则表达式,但不输出,-P表示使用Perl语法,以便|匹配原样,因为\Q..\E结构

IFS=$'|'会使bash使用|而不是空格(SPC,TAB等)作为标记分隔符。