Linuxでこの出力ファイルを取得するより速い方法はありますか

Linuxでこの出力ファイルを取得するより速い方法はありますか
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 1with を使用して停止することができます。grepfile1

while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
  • -Fパターンを文字通りに扱う
  • -m 1grep最初の試合後に退場する

シェル ループは通常は効率的ではありませんが、パターン リストが小さい場合はこのケースでは使用できます。

より速い代替手段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。一致する場合は、その行を出力し、キーを削除します。

関連情報