パイピング後のスクリプト変数をAWKに渡す

パイピング後のスクリプト変数をAWKに渡す

私が書いたスクリプトで変数の割り当てに問題がありますawk。コマンドはawk関数の内部にあり、3つの変数がスクリプト内の他の場所から関数に渡されます。私は以前awkVariables:to break the commandを使ってこれを行ったことがありますが、awk ... '"$var"' ... 明らかにこれはやや粗雑なアプローチであり、スイッチを介してawk変数を割り当てることができます-v

これが私がしたいことです:

my_function() {
  command1 \
  | command2 \
  | awk -v var1="$1" -v var2="$2" -v var3="$3" '{
                FS="[ ,\"]+"}/var1=/{
                        for ( i=2; i<NF; i++) {
                                        if ( var2 ){
                                                var3; next;
                                        }
                                }
                        }
                {
                        fname=$0
        }'
}

...

my_function "$firstArg" "$secondArg" "$thirdArg"

usingの出力によれば、awkコマンドの先頭で変数の割り当てが正しく行われますが、コマンドはこの方法ではなく何も返さないため、正しく動作することがわかりますset -xawkawk ... '"$var"' ...

ここに何か抜けたような感じがします。

ベストアンサー1

次のようなことをしたいようです。

my_function() {
    command1 |
    command2 |
    awk -v var1="$1" -v var2="$2" -v var3="$3" '
        BEGIN { FS="[ ,\"]+" }
        $0 ~ (var1"=") {
            for ( i=2; i<NF; i++) {
                if ( $0 ~ var2 ) {   # maybe just "if (var2)", depends on context
                    var3        # NOTE: this line does nothing
                    next
                }
            }
        }
        { fname=$0 }      # NOTE: this is populating a variable thats never used.
    '
}

...

my_function "$firstArg" "$secondArg" "$thirdArg"

はい、awk ... '"$var"' ...本当にひどいです。考慮する:

$ var=$(printf 'a\nb')
$ echo "$var"
a
b

明らかで理想的な出力:

$ awk -v foo="$var" 'BEGIN{print foo}'
a
b

ぼやけて不要な出力:

$ awk 'BEGIN{print '"$var"'}'

$ awk 'BEGIN{print "'"$var"'"}'
awk: cmd. line:1: BEGIN{print "a
awk: cmd. line:1:             ^ unterminated string
awk: cmd. line:1: BEGIN{print "a
awk: cmd. line:1:             ^ syntax error
$

バラよりawkスクリプトでシェル変数を使用する方法awkスクリプトでシェル変数値を使用するさまざまな方法についての完全な議論です。-vシェル変数の内容によっては、usingが間違ったアプローチである可能性があり、ENVIRON[]orを使用するARGV[]方が良いかもしれません。

質問のスクリプトで行った方法は、入力行ごとに一度設定するように要求しましたが、すでに行が分割された後は、設定したFSが最初の入力行に適用されないために変更さ{FS="[ ,\"]+"}れました。BEGIN{FS="[ ,\"]+"}合計ではなく、1行に1回ずつ設定することです。違いを見てください。

$ printf 'a,b\nc,d\n' | awk '{FS=","} {print $1}'
a,b
c

$ printf 'a,b\nc,d\n' | awk 'BEGIN{FS=","} {print $1}'
a
c

var3;あなたが何をしたいのかは明らかではありませんが、それが何をするのか - 何もありません。

コード構造がプログラムの制御フローを反映するように改行をインデントして使用する方法に注意してください。あなたの質問にあるコードのインデントなどはそうしませんので、コードを混乱させます。後で上記のスタイルでコードを整理してみて、方法がgawk -o-わからない場合は、実行して良いプリントがそれを構築します。

おすすめ記事