以下のような巨大なファイルがあります。 2番目の列の値が60、30などである場合、行を削除します。これらの値はすべて、別のファイルからコンマ区切りファイルで取得します。
position_id risk_measure_id Scenario_id value_usd
1 60 0 300.8
2 30 0 400.6
3 45 90 300.7
4 60 0 200.9
5 30 9 400.8
6 60 10 4000.9
8 20 0 5000.9
以下のawk
コマンドを使用して実現できますが、除外する値が複数ある場合は簡単な方法があります。
$ awk '{ if ($2!=60 && $2!=25 && $2!=30) print $0}' test.txt
position_id risk_measure_id Scenario_id value_usd
3 45 90 300.7
8 20 0 5000.9
値を別のファイルに入れます。
values
:
60
25
30
次に、それらをawk
の配列に読み取ります。
awk 'FNR == NR {arr[$0] = 1; next} !($2 in arr)' values test.txt
FNR == NR
は、最初のファイルを読み取るときにtrueを保持するため、最初のブロックは値の読み取り中にのみ実行されます。 next
のため、!($2 in arr)
は2番目のファイルに対してのみ実行されます。
Awkはコードブロックの前の一致条件を使用して行を出力できるため、コマンドをさらに簡略化できます。if
ステートメントとコードブロックは不要です。行のみを印刷する場合は、コードブロックを完全にスキップできます。
$ awk '$2!=60 && $2!=25 && $2 != 30' input.txt
position_id risk_measure_id Scenario_id value_usd
3 45 90 300.7
8 20 0 5000.9
別の解決策は、配列を使用することです:
awk -v values="60 30 25" 'BEGIN{split(values,array)};{ flag=0; for(val in array) if (array[val] == $2) flag=1; if (flag==0) print }' input.txt
そこで起こることは、スペースで区切られた、必要なすべての値を持つ文字列を作成することです。 BEGINステートメントでは、配列に分解します。メインコードブロックは、各行の読み取り時にフラグ変数を0に設定し、配列内のすべての値をループして、フィールド#2が配列内の何かと一致するかどうかを確認します。存在する場合、フラグを1に設定します。ループが終了した後、ループが何かを見つけてフラグを設定するかどうかを確認し、そうでない場合は行を出力します。
このアプローチの短いバージョンでは、next
コマンドを使用して、除外された値が見つかった場合にループを中断します。このように、print
関数に到達するのは、除外された値が見つからない場合のみです。
awk -v values="60 30 25" 'BEGIN{split(values,array)};{for(val in array) if (array[val] == $2) next; print}' input.txt