awk / shellで同じレコードを持つ2つのファイルを1行ずつマージする方法は?

awk / shellで同じレコードを持つ2つのファイルを1行ずつマージする方法は?

私は最初にawkとshellに触れ、shell / awkを使用して両方のファイルを同じレコードの行にマージする方法を知りたいと思います。 file1とfile2の名前の順序は異なる場合があります。同じレコードを持つ行だけをマージしたいと思います。助けてください。

file1.txt
Mary 68 
Tom 50 
Jason 45
Lu 66

file2.txt
Jason 37
Tom 26
Mary 74
Tina 80

mergefile.txt
Marry 68 74
Tom 50 26
Jason 45 37 

awkを試しましたが、スクリプトの実行には少し時間がかかります。より高速で簡単なツールがあるかどうか疑問に思います。

cat file1.txt | while read line
do
    score1=$( echo $line | awk '{print $2}');
    name1=$( echo $line | awk '{print $1}');

    cat file2.txt | while read l
    do
        score2=$( echo $l | awk '{print $2}');
        name2=$( echo $l | awk '{print $1}');
        if [[ $name1 == $name2 ]]
        then
            echo "$name1 $score1 $score2" >> mergefile
            break
        fi
    done
done

答え1

awkを使用するには:

$ awk 'NR==FNR {a[$1] = $2; next} $1 in a {print $1, $2, a[$1]}' file2.txt file1.txt 
Mary 68 74
Tom 50 26
Jason 45 37

ソートは不要で、2番目のファイルで指定された順序で出力されます。

説明する:

  • NR==FNR最初の名前付きファイルからレコードを選択する正規の方法。
  • {a[$1] = $2; next}最初のフィールドのキーと2番目のフィールドの値で配列を入力します。
  • $1 in a最初のフィールドが最初のファイルにすでに表示されている場合。
  • {print $1, $2, a[$1]}2番目のファイルのキーと値、1番目のファイルの値を印刷します。

答え2

これは職業だと思います。join、リレーショナルデータベースオペレータ

join <(sort file1.txt) <(sort file2.txt)

テスト

$ cat file1.txt
Mary 68
Tom 50
Jason 45
Lu 66

$ cat file2.txt
Jason 37
Tom 26
Mary 74
Tina 80

$ join <(sort file1.txt) <(sort file2.txt)
Jason 45 37
Mary 68 74
Tom 50 26

joinPOSIXで指定された標準ツールです。

マニュアルjoinページには次のように記載されています。

The files file1 and file2 shall be ordered in the collating sequence of sort -b on the 
fields on which they shall be joined, by default the first in each line. All selected 
output shall be written in the same collating sequence.

関連情報