awkを使用して他のファイルの数を使用してファイルから行を正しく抽出するにはどうすればよいですか?

awkを使用して他のファイルの数を使用してファイルから行を正しく抽出するにはどうすればよいですか?

私はbashシェルを使用しています。行番号を持つファイルがある場合

1
4
7
9

最初の要素が数字で、その後にテキスト文字列が続く別の行ファイル

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

awk最初の数字が最初のファイルに属している場合にのみ、2番目のファイルから行を抽出するコマンドをどのように書くことができますか?上記の例では、次のような結果が出ることが予想されます。

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

私はこれを試しました

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

しかし、3番目のファイルでは何も生成されません。

答え1

,2番目のファイルはカンマで区切られているため、コマンドラインオプションを使用してawkフィールド区切り文字を-に設定する必要があります。-F

awk -F, 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

またはFS組み込み変数を介して:

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file FS=, /tmp/second_file > /tmp/third_file

後者のアプローチを使用すると、最初のファイルがコンマで区切られず、複数のフィールドがある場合を処理できます。

答え2

使用幸せ(以前のPerl_6)

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] == any(@a);'  file.csv

#OR

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] ~~ any(@a);'  file.csv

RakuはPerlファミリーのプログラミング言語です。数値リストを取得してBEGIN配列に保存するとき@a。その後、フラグは-ne自動的に印刷せずにコマンドラインからファイルを読み込みます(awk同様の動作)。

ここで、行はテーマ変数($_)(カンマの上)として読み取られ、split最初の要素()が得られます。数値等価演算子(最初のコード例)またはRakuのスマートマッチ演算子を使用して[0]これらの要素を比較します。演算子の右側にある配列はノードになります。条件が成立すると、条件に応じて行が出力されます。==~~@aany()ifput

入力例:

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

出力例(nbr_list.txt1,4,7,9で構成されるファイルを使用):

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

結合ポイントは自動的にスレッド化されるので興味深いです。上記の問題については、one()コネクタがより効率的に動作する可能性があります。


別の方法はセットを使用することです。つまり、行番号をsに変換することSetですInt。データは行単位で読み取られ、各最初の列は強制的に変換され、セットの要素であることがInt確認されます。(elem)infix(elem)または infix 、 (Unicode 記号) は、次のコードで使用できます。

~$ raku -ne 'BEGIN my $set1 = Set.new("nbr_list.txt".IO.lines.map: *.Int);  \
             .put if $_.split(",").[0].Int (elem) $set1;'  file

Rakuセットには固有の値しか含めることができないため(つまり、入力は「固有」です)、2番目の例ではファイルの重複エントリを削除します"nbr_list.txt"。これは実際にOPが望むものかもしれません。

https://docs.raku.org/type/Junction
https://docs-stage.raku.org/type/Junction
https://raku.org

答え3

これを「結合」と呼びます。 coreutilsにはjoinテキストファイルをリンクするツールがあります。

join -t, -j1 --nocheck-order first_file second_file
1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

説明する:

  1. -t,- フィールド区切り文字としてカンマを使用します。
  2. -j1- 最初のフィールドを追加
  3. --nocheck-order- Joinを使用するにはファイルをソートする必要がありますが、数値ソートは好きではありません。したがって、辞書の順序をチェックし、「10」が前に来る「9」について文句を言うのを防ぎます。両方のファイルの最初の列が同じアルゴリズムを使用してソートされている限り、まだ機能します。

関連情報