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の列1の値がファイル5の列5の値と一致する場合、その行は出力に印刷されず、出力に一致しない他の行がなければなりません。 。試しましたが、期待した結果が得られませんでした。
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)
テストに変更し(初心者にとっては理解しにくいのでボーナスです!)、すべてを1行に(!$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
2番目のファイルでは、5番目のフィールドにはすでに論理要素ORが含まれています。
awk '
NR==FNR {A[$1]; next}
{for(i in A)
if(i ~ "^("$5")$") next
print}
' RS='[\n|]' file1 RS='\n' file2
これで、条件付き行の始まりと終わり、および括弧のアンカーポイントのみを置き換えることができます。