比较COLUMN1,输出{列1文件1}不会在文件2
问题描述:
下面存在是我的文件1项内容:比较COLUMN1,输出{列1文件1}不会在文件2
123|yid|def|
456|kks|jkl|
789|mno|vsasd|
,这是我的文件2内容
123|abc|def|
456|ghi|jkl|
789|mno|pqr|
134|rst|uvw|
我想在基于文件2文件1进行比较的唯一的事情是第1列。根据上述文件,则输出只能输出:
134|rst|uvw|
行与行比较不是答案,因为第2列和第3列都包含不同的内容,但只有第1列包含两个文件中完全相同的内容。
我该如何做到这一点?
目前我在我的代码中使用这样的:
#sort FILEs first before comparing
sort $FILE_1 > $FILE_1_sorted
sort $FILE_2 > $FILE_2_sorted
for oid in $(cat $FILE_1_sorted |awk -F"|" '{print $1}');
do
echo "output oid $oid"
#for every oid in FILE 1, compare it with oid FILE 2 and output the difference
grep -v diff "^${oid}|" $FILE_1 $FILE_2 | grep \< | cut -d \ -f 2 > $FILE_1_tmp
答
可以在Awk
做到这一点很容易!
awk 'BEGIN{FS=OFS="|"}FNR==NR{unique[$1]; next}!($1 in unique)' file1 file2
Awk
作品通过一次处理输入线一个。并且有Awk
提供的特殊子句,BEGIN{}
和END{}
,它包含了在文件处理之前和之后运行的动作。
因此部分是在文件处理发生之前设置的,而FS
和OFS
是Awk
中的特殊变量,它们代表输入和输出字段分隔符。既然你提供的由|
是去限制一个文件,你需要通过设置FS="|"
也与|
打印回解析它,所以设置OFS="|"
命令的主要部分来自后BEGIN
条款,部分FNR==NR
是为了处理命令中提供的第一个文件参数,因为FNR
跟踪两个文件合并的行号和NR
仅当前文件。因此,对于在所述第一文件中的每个$1
,值被散列到称为unique
然后当下文件处理发生时,部分!($1 in unique)
将下降在第二个文件中,其$1
值不是int散列阵列的那些行的阵列。
答
下面是一个使用join
,sort
和grep
join -t"|" -j 1 -a 2 <(sort -t"|" -k1,1 file1) <(sort -t"|" -k1,1 file2) |\
grep -E -v '.*\|.*\|.*\|.*\|'
join
在这里所做的两件事情的另一个一行。它将两个文件中的所有行与匹配的键匹配,并使用-a 2
选项还打印file2中不匹配的行。
由于join
需要对输入文件进行排序,我们对它们进行排序。
最后,grep
删除输出中包含多于三个字段的所有行。
给定文件1和文件2,你只想输出'134 | rst | uvw |'?那么为什么不进行基于行的比较工作?如果要合并具有文件1和文件2中匹配列1的行,可以使用'join -t'|' file1 file2',然后使用'cut'来只输出相关的列。 – rubystallion
我的输入文件包含数千行,不可能知道要删除哪行 – MFAY