2017-08-02 86 views
1

下面存在是我的文件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 
+0

给定文件1和文件2,你只想输出'134 | rst | uvw |'?那么为什么不进行基于行的比较工作?如果要合并具有文件1和文件2中匹配列1的行,可以使用'join -t'|' file1 file2',然后使用'cut'来只输出相关的列。 – rubystallion

+0

我的输入文件包含数千行,不可能知道要删除哪行 – MFAY

回答

4

可以在Awk做到这一点很容易!

awk 'BEGIN{FS=OFS="|"}FNR==NR{unique[$1]; next}!($1 in unique)' file1 file2 

Awk作品通过一次处理输入线一个。并且有Awk提供的特殊子句,BEGIN{}END{},它包含了在文件处理之前和之后运行的动作。

因此部分是在文件处理发生之前设置的,而FSOFSAwk中的特殊变量,它们代表输入和输出字段分隔符。既然你提供的由|是去限制一个文件,你需要通过设置FS="|"也与|打印回解析它,所以设置OFS="|"

命令的主要部分来自后BEGIN条款,部分FNR==NR是为了处理命令中提供的第一个文件参数,因为FNR跟踪两个文件合并的行号和NR仅当前文件。因此,对于在所述第一文件中的每个$1,值被散列到称为unique然后当文件处理发生时,部分!($1 in unique)将下降在第二个文件中,其$1值不是int散列阵列的那些行的阵列。

+1

+1 Nice!我认为你的意思是“** ...所以在上面设置了'OFS =”|“'... **”。我试图修复它,但我不允许编辑少于6个字符,很奇怪。 – Anubis

+0

感谢您的帮助。我完全理解了解释,但是我错过了什么?我在测试命令时不断收到语法错误。我做了一些研究,但发现语法已经正确 – MFAY

+0

@MAY:你是否正在运行命令?你有什么版本的Awk? – Inian

1

下面是一个使用joinsortgrep

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删除输出中包含多于三个字段的所有行。