【问题标题】:Show Difference Between TSV by Column按列显示 TSV 之间的差异
【发布时间】:2017-03-08 07:08:51
【问题描述】:

我正在比较两个 TSV 文件,它们是这样生成的包列表:

rpm -qa --qf "%{name}\t%{version}\t%{license}\n" | sort -n > packages

这会生成一个制表符分隔的文件,例如:

alsa-firmware   1.0.28  GPL+ and BSD and GPLv2+ and GPLv2 and LGPLv2+
alsa-lib        1.0.28  LGPLv2+
alsa-tools-firmware     1.0.27  GPLv2+

在另一个系统上,我正在运行相同的命令,其中安装了更多的软件包。我想要第二台服务器上这些附加软件包的列表。这里棘手的部分是我希望匹配列表不按版本过滤。 Comm 和 Diff 检查整行,我只想按第一个“列”过滤。

例如,如果第二台服务器具有以下软件包列表:

acl     2.2.51  GPLv2+
alsa-firmware   2.0.28  GPL+ and BSD and GPLv2+ and GPLv2 and LGPLv2+
alsa-lib        2.0.29  LGPLv2+
alsa-tools-firmware     2.0.27  GPLv2+
audit   2.4.1   GPLv2+
binutils        2.23.52.0.1     GPLv3+

我正在寻找一个命令(sed、awk、comm、diff 等),它将返回第一列的差异 - 在本例中为:

acl     2.2.51  GPLv2+
audit   2.4.1   GPLv2+
binutils        2.23.52.0.1     GPLv3+

请注意,alsa 软件包已更改版本,但仍具有相同的软件包名称。

【问题讨论】:

    标签: awk sed diff


    【解决方案1】:

    使用awk,仅匹配两个文件中的第一列

    $ awk 'NR==FNR{a[$1]; next} !($1 in a)' file1 file2
    acl     2.2.51  GPLv2+
    audit   2.4.1   GPLv2+
    binutils        2.23.52.0.1     GPLv3+
    


    或者将第一列作为搜索模式传递​​给grep。这假定file2 中的其他列与搜索词不匹配

    $ awk '{print $1}' file1 | grep -vFf - file2
    acl     2.2.51  GPLv2+
    audit   2.4.1   GPLv2+
    binutils        2.23.52.0.1     GPLv3+
    


    使用sed,类似于grep 解决方案,但如果file1 的第一列包含任何正则表达式元字符,则容易出错

    $ sed -f <(sed -E 's|^(\S+).*|/\1/d|' file1) file2
    acl     2.2.51  GPLv2+
    audit   2.4.1   GPLv2+
    binutils        2.23.52.0.1     GPLv3+
    

    【讨论】:

    • 第一个命令,awk 本身是正确的方法,但 ++ 除了使用 up 循环之外什么都不做。不应使用 awk+grep,因为它会错误地比较/匹配整行而不是第一个字段,并且由于您所说的原因以及其他原因,应避免嵌套 sed。
    • @EdMorton 谢谢,我不知道a[$1] 就够了:)
    • 干得好,伙计们! awk 确实给了我想要的结果。
    猜你喜欢
    • 2011-03-23
    • 2015-08-08
    • 2017-11-02
    • 1970-01-01
    • 2020-06-19
    • 2017-11-17
    • 2015-08-12
    • 2012-08-23
    • 1970-01-01
    相关资源
    最近更新 更多