AWK: シェル変数を awk に渡す

AWK: シェル変数を awk に渡す

私は合格しようとしています変数シェル スクリプトからテーブルのパターン認識サブセットへの引数の数。これまでの私の試みは次のとおりです。

ファイル「infile」:

    ID,GROUP
    1,GROUP2    
    2,GROUP2    
    3,GROUP4    
    4,GROUP4    
    5,GROUP5    
    6,GROUP5    
    7,GROUP23   
    8,GROUP23   
    9,GROUP23   

ファイル subset.sh:

    #!/bin/sh
    rm -f outfile_$week

    week = $1
    shift

    for TOKEN in "$@"
    do

    echo "adding records for" $TOKEN

    awk -F "," -v group = $TOKEN '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile >> outfile_$week
    done

また、group = "$TOKEN"、"group = $TOKEN"、そして両方を一重引用符で囲んで試してみました。次のように送信します。

    sh subset.sh 061314 GROUP2 GROUP23

私が受け取ったエラーは驚くほど情報不足です

    Usage: awk [-F fs][-v Assignment][-f Progfile|Program][Assignment|File] ...

どのような助けでも大歓迎です、ありがとうございます!

編集: 走ってみた

    awk -F "," -v group ="GROUP1" '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile

無駄でした... (上記と同じエラー) これが起こる理由を知っている人はいますか?

答え1

次のように記述します。

-v group="$TOKEN"

の代わりに を使用すると-v group = $TOKEN、 で構文エラーが発生しますawk

答え2

あなたが望んでいるのは次のようなことのようです:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 && $2 in group' "$@" < infile

または、引数を 2 番目の列と一致する正規表現として考慮したい場合は、次のようにします。

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 {
    for (i in group) if ($2 ~ i) {print; next}
  }' "$@" < infile

答え3

すぐに問題になるのは、等号の周りのスペースです。-vオプションへの引数は割り当てである必要があります。Awk は-v、 への引数、スクリプト ( =)、ファイル名 ( の値TOKEN、スクリプト、ファイル名) の順に認識します。

上記のシェル スクリプトでも同様のエラーが発生しました:week = $1である必要がありますweek="$1"

ところで、コマンド置換は常に二重引用符で囲むたとえば、TOKENが の場合*、現在のディレクトリ内のファイルのリストに置き換えられます。

awk -v "group=$TOKEN"

ただし、awk は代入の右側を awk 構文のリテラルとして扱うため、groupの値は設定されません。たとえば、 の値が 7 文字の文字列 である場合、awk 変数は6 文字の文字列 に設定されます。ここで、はバックスペース文字 (バイト値 8) です。TOKENTOKENfoo\bargroupfoo␈ar

変数を awk スクリプトに渡す最も簡単な方法は、変数を環境にエクスポートし、配列を介して使用することですENVIRON

さらに、groupawk スクリプトのどこにも変数を使用していません。正規表現は、/group/5 文字の文字列 を含む任意の文字列と一致しますgroup。フィールドが の値と正確に一致するかどうかをチェックする場合group(つまり、 の値が の場合、TOKENGROUP2含むフィールドはGROUP24一致しない)、等価演算子 を使用します==

  export TOKEN
  awk -F "," '{ if (FNR > 2 && $2 == ENVIRON["TOKEN"]){print $0} }' infile >> outfile_$week

print $0以下は、awk の条件アクション構文 (ここではアクションはデフォルトなので省略) を使用し、毎回出力ファイルを開かないようにするために、さらに少し簡略化されたスクリプト全体です。

#!/bin/sh
week="$1"
shift
for TOKEN in "$@"
do
  echo "adding records for" $TOKEN
  awk -F "," 'FNR > 2 && $2 == ENVIRON["TOKEN"]' infile 
done >"outfile_$week"

見るステファン・シャゼラスの回答入力ファイルを複数回処理する必要がない、より高度な awk の使用方法。

関連情報