awk
(または)を使用して一部のデータを変換しており、gawk
出力を再印刷する前に入力フィールドの1つを削除したいと思います。
私が達成したいことは次のとおりです
~ $ echo 'field1,field2,field3' | awk -F, '{transform($1); delete($2); print $0;}'
new_field1,field3
$2
その結果、空の文字列を割り当てることはできませんnew_field1,,field3
(2つのカンマに注意してください)。
必要なフィールドだけを明示的に印刷できますが、フィールドが3つよりはるかに多く、最後にオプションのフィールドがあるので(ここには表示されません)、それほどエレガントではありません。だからprint $0
最初にいくつかのフィールドを削除することを好みます。
どんなアイデアがありますか?
ベストアンサー1
awkからフィールドを削除するのは非常に難しいです。これは単純な(しばしば必要な)作業のように見えますが、思ったよりも難しいです。
バラより追加の区切り文字が印刷されないように、awkからフィールドを完全に削除する方法はありますか? Stack Overflowの素晴らしいヒントです。
rmcol()
U&Lにコピーがあるように、@ghotiの答えから関数をコピーしました。
function rmcol(col, i) {
for (i=col; i<NF; i++) {
$i=$(i+1)
}
NF--
}
現在の入力行から指定された列を削除し、一致のためにフィールドカウンタ(NF
)を減らします。
私はあなたの機能が何であるかわからないtransform()
ので、それを繰り返そうとしません。ただし、以下はrmcol()
1行で使用する例です。awk
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i) {
for (i=col; i<NF; i++) {
$i=$(i+1)
}
NF--
}
{ rmcol(2); print; }
'
field1,field3
しかし、入力行から複数のフィールドを削除する必要がある場合は、最も簡単で簡単な方法は逆の順序で削除することです。それは、最も高い数のフィールドを最初に削除してください。。なぜ?これは、低い番号のフィールドが削除されるたびに、高い番号のフィールドの番号が再割り当てされ、どのフィールド番号がどのフィールドに属するかを追跡するのが難しいからです。
ところで、delete()
inはawk
配列の要素を削除するために使用され、入力行からフィールドを削除するためには使用されません。split()
各入力行(on)を配列に配置して2番目の配列要素を削除できますが、その後、各フィールドをコンマ(または)で区切って配列を印刷する関数を作成する必要がありますFS
。join()
OFS
awk
これはすべての配列が連想配列であるため、予想よりも複雑です(つまり、いいえ数値インデックス) - だからdelete(array[2])
に慣れる配列要素3+を要素2+に自動的に移動します。delete()
入力フィールドと同様に、配列でもほぼ同じことを行うには、独自のラッパー関数を作成する必要があります。rmcol()