查找特定列中的常见元素 >2 个文件,并从每个文件中打印相应的行



我的问题是很久以前提出的问题的延伸。问题是在>linux中的2个文件,根据特定列中的匹配条目。

问题是(我指的是这篇文章:在>2个文件中找到常见元素(

我有三个文件,如下所示

file1.txt

"aba" 0 0 1
"abc" 0 1
"abd" 1 1 
"xxx" 0 0

file2.txt

"xyz" 0 0
"aba" 0 0 0 1
"xxx" 0 0
"abc" 1 1

file3.txt

"xyx" 0 0
"aba" 0 0 
"xxx" 0 0 0 1
"abc" 1 1

我想根据前两列在所有三个文件中找到相似的元素。

现在,我不仅想从所有文件中找到相似的元素,还想打印所有文件中相应的行。请注意,我的任何文件都没有排序。

注意:我希望只从所有文件中匹配第1列中的元素,并按顺序打印文件中相应的行。

因此,在这个例子中,我想要的输出是:

"xxx" 0 0 0 0 0 0 1
"aba" 0 0 1 0 0 0 1 0 0
"abc" 0 1 1 1 1 1 

其中它正在按顺序打印来自文件1-3的匹配元素($1(。

一位用户为此提供了以下解决方案:

awk '
FNR == NR { 
arr[$1,$2] = 1
line[$1,$2] = line[$1,$2] ( line[$1,$2] ? SUBSEP : "" ) $0
next
}
FNR == 1 { delete found }
{ if ( arr[$1,$2] && ! found[$1,$2] ) { arr[$1,$2]++; found[$1,$2] = 1 } }
END { 
num_files = ARGC -1 
for ( key in arr ) {
if ( arr[key] < num_files ) { continue }
split( line[ key ], line_arr, SUBSEP )
for ( i = 1; i <= length( line_arr ); i++ ) { 
printf "%sn", line_arr[ i ]
} 
} 
}
' file1.txt file2.txt file3.txt

但是,这与前2列匹配,并且只打印列表中第一个出现的文件(此处为file1.txt(的整行

它给出的输出是:

"xxx" 0 0
"aba" 0 0 
"aba" 0 0 1

有没有办法修改这个脚本,让它打印所有文件中的匹配行。我需要线条并排显示,格式如上所述。我的文件是制表符分隔的,所以我希望输出也是制表符分隔。另一个重要的点是,所有文件都包含相同的列数,但不同的行数。

给定:

$ head file?.txt
==> file1.txt <==
"aba" 0 0 1
"abc" 0 1
"abd" 1 1 
"xxx" 0 0
==> file2.txt <==
"xyz" 0 0
"aba" 0 0 0 1
"xxx" 0 0 0 1
"abc" 1 1
==> file3.txt <==
"xyx" 0 0
"aba" 0 1 0
"xxx" 0 0 0 1
"abc" 1 1

假设文件中两次出现的"aba"是打字错误(来自注释(,您可以这样做:

$ awk '{cnt[$1]++
s=""
for (i=2;i<=NF;i++) s=s OFS $i
seen[$1]= seen[$1] s}
END{for (e in seen) if (cnt[e]>1) print e, seen[e]}' file?.txt

打印:

"aba"  0 0 1 0 0 0 1 0 1 0
"abc"  0 1 1 1 1 1
"xxx"  0 0 0 0 0 1 0 0 0 1

来自评论。

给定:

$ head file{1..3}.txt
==> file1.txt <==
"aba" 0 0 1
"abc" 0 1
"abd" 1 1 
"xxx" 0 0
==> file2.txt <==
"xyz" 0 0
"aba" 0 0 0 1
"xxx" 0 0 0 1
"abc" 1 1
==> file3.txt <==
"xyx" 0 0
"xxx" 0 0 0 1
"abc" 1 1

(注意文件3中删除了"aba"…(

你可以使用这个awk:

$ awk 'FNR==1 {fcnt++} 
{cnt[$1]++
s=""
for (i=2;i<=NF;i++) s=s OFS $i
seen[$1]= seen[$1] s}
END{for (e in seen) if (cnt[e]==fcnt) print e, seen[e]}' file{1..3}.txt

打印:

"abc"  0 1 1 1 1 1
"xxx"  0 0 0 0 0 1 0 0 0 1

最新更新