a.txtの3つのデータ(A、B、num:xxx)に基づいてb.txtの行を選択したいと思います。
a.txt
A B num : 580
A B num : 581
A B num : 582
b.txt
10 E1 A Z1 B Z2 num : 580 Z3 582 Z4
11 E2 C Z1 B Z2 num : 581 Z3 580 Z4
12 E3 A Z1 B Z2 num : 581 Z3 580 Z4
14 E3 S Z1 B Z2 num : 582 Z3 581 Z4
15 E2 A Z1 B Z2 num : 582 Z3 581 Z4
出力
10 E1 A Z1 B Z2 num : 580 Z3 582 Z4
12 E3 A Z1 B Z2 num : 581 Z3 580 Z4
15 E2 A Z1 B Z2 num : 582 Z3 581 Z4
私のコード
awk 'NR==FNR{pattern[$0];next} ($3 && $5 && "$7 $8 $9" in pattern)' a.txt b.txt > GoodFile.txt
これは何の問題ですか?ありがとうございます。
答え1
連想配列のキーはpattern
次のとおりです。文字列の連結フィールドとフィールドの区切り記号、つまり
$ awk 'NR==FNR{pattern[$0]; next} $3" "$5" "$7" "$8" "$9 in pattern' a.txt b.txt
10 E1 A Z1 B Z2 num : 580 Z3 582 Z4
12 E3 A Z1 B Z2 num : 581 Z3 580 Z4
15 E2 A Z1 B Z2 num : 582 Z3 581 Z4
a.txt
あるいは、より強力であるかもしれません(区切り文字が単一の空白であると仮定していないので)、明示的なSUBSEP
awk変数を使用してください。エドモートンが提案したように:
awk 'NR==FNR{pattern[$1,$2,$3,$5]; next} ($3,$5,$7,$9) in pattern' a.txt b.txt
答え2
拡張GNU sed
正規表現モードをオンにして-E
自動印刷モードスペースをオフにすると、-n
図のように解決できます。
まず、sedコードの記述を簡素化するために、いくつかの補助シェル変数を定義します。
$ f='(\S+)' g='\s+\S+\s+' fg="$f$g"
$ Ss='\S+\s+' fs="$f\s+"
$ re="$Ss $Ss $fg $fg $fs $fs $fs"
$ sed -En "
s/$f/&/6;tb
s/\s+/ /g;s/^ | \$//g
H;d
:b;G
\#^${re// /}.*\n\1 \2 \3 \4 \5(\n|$)#P
" a.txt b.txt
¶最初に、空白ではなく6番目のブロックの存在でa.txtまたはb.txtの行を識別します。その場合は、ファイルb.txtでsedコードのラベルbに移動します。
¶ それ以外の場合は、a.txt ファイルの場合は行を切り取り、空白を圧縮します。その後、保存します。
¶b.txtファイルの行に対して、b.txtの行構造に従って作成された$ reシェル変数を挿入します。また、文章を書くときは、明確にするために空白を振りましたが、今は削除する必要があります。P
b.txt のブロック番号 3、5、7、8、および 9 が a.txt 行のどこにでも見つかった場合、パターン空間の前部を印刷します。