AWKから入力フィールドを削除する方法は?

AWKから入力フィールドを削除する方法は?

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番目の配列要素を削除できますが、その後、各フィールドをコンマ(または)で区切って配列を印刷する関数を作成する必要がありますFSjoin()OFS

awkこれはすべての配列が連想配列であるため、予想よりも複雑です(つまり、いいえ数値インデックス) - だからdelete(array[2]) に慣れる配列要素3+を要素2+に自動的に移動します。delete()入力フィールドと同様に、配列でもほぼ同じことを行うには、独自のラッパー関数を作成する必要があります。rmcol()

おすすめ記事