cat file_1
my colour is red
my rose is red
my colour is blue
my rose id blue
cat file_2
red
blue
cat output_file should be
my colour is red
my colour is blue
ここで私は使用しています
cat file_2 | while read line;do cat file_1 | grep "$line" | head -1;done
pattern "red" and "blue"
ここで私は、に存在する一番上の行を取得しようとしていますfile_2
他に何か方法はありますか?as fast as possible
、whileループに時間がかかります
答え1
while
構造を使用して からのパターンをループしfile2
、 での最初の一致後に-m 1
with を使用して停止することができます。grep
file1
while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
-F
パターンを文字通りに扱う-m 1
grep
最初の試合後に退場する
シェル ループは通常は効率的ではありませんが、パターン リストが小さい場合はこのケースでは使用できます。
より速い代替手段、xargs
:
xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
-P
より多くのパターンには、より多くの並列プロセス ( ) を使用します。
例:
% while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
my colour is red
my colour is blue
% xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
my colour is blue
my colour is red
答え2
file_2 の行と一致する file_1 の最初の行を印刷するには:
$ awk 'FNR==NR{a[$0];next} {for (line in a) if ($0~line) {print; delete a[line]}}' file_2 file_1
my colour is red
my colour is blue
この方法では、各ファイルを 1 回だけ読み取ります。
使い方
FNR==NR{a[$0];next}
これにより、file_2 のすべての行が連想配列のキーとして保存されます
a
。for (line in a) if ($0~line) {print; delete a[line]}
file_1 の各行について、配列内のキーと一致するかどうかを確認します
a
。一致する場合は、その行を出力し、キーを削除します。