awk を使用してファイルからデータを抽出する際の問題

awk を使用してファイルからデータを抽出する際の問題

大きなデータ ファイルがあり、列 1 の値に基づいてそれを小さなファイルに分割したいと考えています。たとえば、列 1 には 1 から 10 までの数字が 10 回あり、100 行になりますが、数字が '1'、'2'、'3' などのすべての行を独自のファイル (できればソートなし) に含めたいと考えています。また、コマンドを 10 回実行したくないので、ループ内に収めたいと考えています。

私のファイルは次のようになります:

  • text.txt

    ここに画像の説明を入力してください

  • ID.txt

    1
    2
    3
    4
    

試したコマンド:

cat ID.txt | while read line; do awk '$1 == ${line}' test.txt >$line.txt;done

要約すると、ID.txt ファイルから値 (例: '1') を読み取り、最初の行に '1' が含まれるすべての行を抽出して 1.txt というファイルに格納し、次に 2、3、4 と繰り返し処理することになります。

しかし、どういうわけか「$1 == ${line}」の部分が機能していないと思います

答え1

-v次のオプションを探していますawk:

   -v var=val
   --assign var=val
          Assign the value val to the variable var,  before  execution  of
          the  program  begins.  Such variable values are available to the
          BEGIN rule of an AWK program.

このようなもの:

cat ID.txt | 
    while read line; do awk -vline="$line" '$1 == l' test.txt >"$line".txt;done

これは次のように表現した方がよいでしょう (cat の無駄な使用を避けて):

while read line; do 
    awk -vline="$line" '$1 == l' test.txt >"$line".txt;
done < ID.txt

しかし、これは非常に遅く、非効率的です。の各行に対して、awk全体に対してコマンドを実行しています。 それ自体を読み込んで、一致する行を印刷するだけではいかがでしょうか。test.txtID.txtID.txtawk

awk 'NR==FNR{a[$1]++; next} ($1 in a){print >> $1".txt"}' ID.txt test.txt 

上記は、ID.txt配列の 1 番目のフィールドを保存しますaNRおよび は、「入力ストリームの現在の行」と「現在のファイルの現在の行」を意味するFNR特別な変数です。この 2 つは、最初のファイルが読み取られているときのみ互いに​​等しくなります。したがって、 は最初のファイルの行でのみ実行されます。 は次の行にスキップするように指示するため、2 番目の部分は実行されません。awkNR==FNR{a[$1]++; next}nextawk

2 番目の部分は、現在の行の 1 番目のフィールド (これは 2 番目のファイルでのみ実行されることに注意してください) が配列内に存在するかどうかa(つまり、配列内にあったかID.txtどうか) を確認し、存在する場合は、その行を "field1.txt" というファイルに出力します。

関連情報