大きなデータ ファイルがあり、列 1 の値に基づいてそれを小さなファイルに分割したいと考えています。たとえば、列 1 には 1 から 10 までの数字が 10 回あり、100 行になりますが、数字が '1'、'2'、'3' などのすべての行を独自のファイル (できればソートなし) に含めたいと考えています。また、コマンドを 10 回実行したくないので、ループ内に収めたいと考えています。
私のファイルは次のようになります:
試したコマンド:
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.txt
ID.txt
ID.txt
awk
awk 'NR==FNR{a[$1]++; next} ($1 in a){print >> $1".txt"}' ID.txt test.txt
上記は、ID.txt
配列の 1 番目のフィールドを保存しますa
。NR
および は、「入力ストリームの現在の行」と「現在のファイルの現在の行」を意味するFNR
特別な変数です。この 2 つは、最初のファイルが読み取られているときのみ互いに等しくなります。したがって、 は最初のファイルの行でのみ実行されます。 は次の行にスキップするように指示するため、2 番目の部分は実行されません。awk
NR==FNR{a[$1]++; next}
next
awk
2 番目の部分は、現在の行の 1 番目のフィールド (これは 2 番目のファイルでのみ実行されることに注意してください) が配列内に存在するかどうかa
(つまり、配列内にあったかID.txt
どうか) を確認し、存在する場合は、その行を "field1.txt" というファイルに出力します。