2016-10-26 53 views
0

我比较是产生像这样包列于两个TSV文件: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,通讯,DIFF等)将由第一回的区别列 - 在这种情况下将是:

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

注意ALSA包已经改变了版本,但仍然有相同的包名。

回答

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+ 
+1

第一个命令awk本身是正确的方法,但'++'除了使用循环外什么也不做。不应该使用awk + ​​grep,因为它会错误地比较/匹配整行而不是第一个字段,并且应该避免出于您陈述的原因和其他原因嵌套的seds。 –

+1

@EdMorton谢谢,我不知道'a [$ 1]'就够了:) – Sundeep

+0

伟大的工作家伙! awk的确给了我想要的结果。 – user3063045