file1
HIB12
VH6|KB4
KB4
KB4|LKM98|HIB12
file2
c1 c1 c3 c4 HIB12|LKM98 c6
c1 c1 c3 c4 KB4|LKM98 c6
c1 c1 c3 c4 LL15|VH6
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
c1 c1 c3 c4 AB1 c6
两个文件均以制表符分隔。文件 1 的列 1 与文件 2 的列 5 部分匹配。两列中的值均由“|”分隔如果file1的column1的任何值与file5的column5的任何值匹配,则该行不应在输出中打印,输出中应存在其他不匹配的行。我尝试过但没有得到预期的输出
awk 'BEGIN{FS=OFS="\t"} NR==FNR {a[$1]=$5; next} {for (i in a) if (index(i, $5)) print $0, a[i]}' file2 file1
expected output
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
答案1
使用 GNU awk 进行多字符 RS:
$ awk '
NR==FNR { a[$0]; next }
{ split($5,v,"|"); for (i in v) if (v[i] in a) next; print }
' FS='\t' RS='[[:space:]|]+' file1 RS='\n' file2
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
c1 c1 c3 c4 AB1 c6
或使用任何 awk:
$ awk '
NR==FNR { for (i=1; i<=NF; i++) a[$i]; next }
{ split($5,v,"|"); for (i in v) if (v[i] in a) next; print }
' FS='|' file1 FS='\t' file2
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
c1 c1 c3 c4 AB1 c6
答案2
与任何 awk 兼容。
awk 'BEGIN{FS=OFS="\t"}NR==FNR{split($0,vals,"|");for(i in vals){v[vals[i]]}}NR!=FNR{hide=0;for(j in v){if($5~j){hide=1}};if(!hide){print}}' ./file1 ./file2
我的结果是:
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
c1 c1 c3 c4 AB1 c6
描述:
NR==FNR
: 在第一个文件中NR
和FNR
是相等的。
{v[vals[i]]}
:创建不允许值的关联数组。
if($5~j){hide=1}
:如果第 5 个字段中有不允许的值,则设置隐藏行
hide=0
:重置新行的隐藏状态。
答案3
$ perl -lane '
# is this the first file? ($fc is file counter)
if ($fc == 0) {
# split first field on pipe chars
my @p = split /\|/, $F[0];
# use as keys for %patterns hash
foreach my $p (@p) { $patterns{$p} = 1 };
} else {
print unless $F[4] =~ /$regex/;
};
if (eof) { # end of file
if ($fc == 0) { # is this still the first (zeroth) file?
# use keys of %patterns to build a regular expression
$regex = join "|", keys %patterns;
};
$fc++;
}' file1 file2
c1 c1 c3 c4 ZZ16|YY15 c6
c1 c1 c3 c4 ZZ16 c6
c1 c1 c3 c4 AB1 c6
顺便说一句,这是一个较短的版本,中间变量较少,并且没有注释:
perl -lane '
if ($fc == 0) {
foreach (split /\|/, $F[0]) { $patterns{$_} = 1 };
} else {
print unless $F[4] =~ /$regex/;
};
if (eof) {
$regex = join "|", keys %patterns if ($fc == 0);
$fc++;
}' file1 file2
如果你想让它不可读,你可以缩短变量名称,($c==0)
用更短但等效的测试替换测试(对于新手来说更难理解,所以奖金!)(!$c)
,将其全部压缩成一行并摆脱多余的空格和半字符-冒号没有改变它的运行方式。有些人更喜欢这个——受虐狂的货物崇拜 FTW!
perl -lane 'if(!$c){foreach(split/\|/,$F[0]){$p{$_}=1}}else{print unless $F[4]=~/$regex/};if(eof){$regex=join"|",keys %p if(!$c);$c++}' file1 file2
答案4
在第二个文件中,第五个字段已包含逻辑元素 OR:
awk '
NR==FNR {A[$1]; next}
{for(i in A)
if(i ~ "^("$5")$") next
print}
' RS='[\n|]' file1 RS='\n' file2
剩下的只是替换条件表达式中行的开头和结尾以及括号的锚点。