この問題は別のトピックで議論されていますが、すべての内容を1つにまとめることはできません。
TSVファイルがあります。以下はサンプルラインです:(file1)
NODE_1_length_45927_cov_22.029055_g0_i0 WP_055195622.1 93.1 729 50 0 291 2477 1 729 0.0e+00 1275.4 166486;1897048
最後のフィールドには、で区切られた数字のリストが含まれています;
。
検索パターンのリストを含むファイル(ファイル2)があります。
33090
3041
1897
97100
97101
166486
検索パターンを含む行を出力したいです。
- 最後のフィールドのみ
- ;で区切られた最後のフィールドのすべての数字は一致することができますが、パターンと正確に一致する単語でなければなりません。
これまで私の最善の試みは
awk 'NR==FNR{a[$1]; next} {for (i in a) if ($NF ~ i) print $0}' file2 file1
ただし、これには部分一致が含まれます。たとえば、1897は2番目の数字と一致するため、一致しません。
私は単語全体のさまざまなバリエーションを一致させるためにgawk正規表現を試しました。
awk 'NR==FNR{a[$1]; next} {for (i in a) if ($NF ~ '/\yi\y/') print $0}' file2 file1
awk 'NR==FNR{a[$1]; next} {for (i in a) if ($NF ~ '/[^[:alpha:]]i[^[:alpha:]]/') print $0}' file2 file1
しかし、出力はありません。
どんなに醜いでも、すべてのbashソリューションは素晴らしいでしょう。ただし、それぞれ2000万行の12個のファイルがあるため、ループでこの問題を解決することはできません。早く。
どんな助けでも大変感謝します。
答え1
awk 'NR==FNR{a[$1];next}{n=split($NF,b,";");for(i=1;i<=n;i++){if(b[i] in a){print;break}}}' file2 file1
リリースされたバージョン:
awk '
NR==FNR{a[$1];next}
{
n=split($NF,b,";")
for(i=1;i<=n;i++){
if(b[i] in a){print;break}
}
}
' file2 file1
split($NF,b,";")
最後のフィールドをセミコロンに分割し、結果をb
配列に入れます。b
割り当てられた要素の数を返しますn
。あなたの例の行からn=2
と。b[1]=166486
b[2]=1897048
if(b[i] in a){print;break}
正確に一致するものがある場合は、その行を印刷してループを中断して、同じ行が2回印刷されないようにします。
答え2
Pythonデータ構造は、set
セミコロンで区切られた数字の1つがfile2数字で構成される別のセットで見つかったかどうかを比較して見つける方法を提供します。 Yield が空でなく、交点が設定されている場合は、現在の行を印刷し続けます。
python3 - file1 file2 <<\eof
import sys
data, pat = sys.argv[1:]
rs, fs = '\n', '\t'
with open(pat) as fp, open(data) as fd:
pats = set(fp.read().splitlines())
for l in fd:
s = l.rstrip(rs).split(fs)[-1].split(';')
if set(s) & pats: print(l, end='')
eof
答え3
注文する
awk 'NR == FNR {a[$1];next}FS=";"($NF in a){print $0}' f2 f1
出力
NODE_1_length_45927_cov_22.029055_g0_i0 WP_055195622.1 93.1 729 50 0 291 2477 1 729 0.0e+00 1275.4 166486;1897048