2つのファイルセットがあります。
ファイル1には次のIDが含まれています。
1111
2222
6666
3333
4444
ファイル2にはIDとユーザー名が含まれています。
1873 Neil
1111 Roger
7632 Tim
3333 Oscar
8723 Greg
4444 Roy
6666 Patrick
IDとユーザー名を抽出したいのですが、ファイル1のIDと同じ項目だけを抽出したいと思います。grep -f file1 file2
公開したばかりのように、IDがほとんどない状態で作成された2つのテストファイルに対して通常の作業を行いました。ただし、これを2つの正しいファイルに適用すると、file1には3500個のIDがあり、File2には12000個のID +ユーザー名が含まれ、両方のファイルに表示される3500行を抽出する代わりに12000行を抽出します。ただし、2つのテストファイルといくつかのダミーIDを使用して正しいIDのみを抽出し、残りを維持します。
何が問題なのかについてのアドバイスはありますか?
答え1
以下を使ってこれを行います。参加する代わりにgrep
、これがより適切になります:
$ join <(sort file1) <(sort file2)
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
シェルが欠落している場合プロセスの交換 <( )
、あなたはできます:
sort file1 > new_file1
sort file2 > new_file2
join new_file1 new_file2
医者はこう言いました。
Joinは、同じ結合フィールドを持つ各入力行のペアを標準出力に書き込みます。
バラよりhttp://www.gnu.org/software/coreutils/manual/html_node/join-inspiration.html
指示:
これが正しく機能するには、ソートキーに基づいてファイルをソートする必要がありますjoin
。これがまさに私たちがいくつかを使う理由です。ファイル記述子バックグラウンドで使用プロセスの交換
バラよりhttp://mywiki.wooledge.org/ProcessSubstitutionまたはhttp://mywiki.wooledge.org/BashFAQ/024一般的な用途。
答え2
grep
ユーザー名とIDが同じ行に一致します。join
最初のフィールドの一致は正しく制限されますが、ソートされた入力が必要です。入力に応じてawk
良い選択かもしれません。
awk 'FNR == NR { ids[$1]++; next } ids[$1]' ids users
またはもっと読みやすくするには:
awk 'FNR == NR { ids[$1]; next } $1 in ids' ids users
出力:
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
説明する
awkプログラムは2つの部分に分けられます。最初のファイルを評価する部分と2番目のファイルを評価する部分です。
最初のブロックは最初のファイルに対してのみ評価され、IDが配列ids
に格納されます。読み込み中にこれらのIDが見つかると、users
デフォルトのblock()が呼び出されます{print $0}
。