awk スクリプトでシェル変数を使うには

bash shell awk


外部シェル変数を awk スクリプトに渡す方法をいくつか見つけましたが、 " ' と「」について混乱しています。

まず、シェルスクリプトで試してみました。

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

それからawkを試してみた。

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

なぜ違いがあるのか?

最後にこれを試してみました。

$ awk 'BEGIN{print " '$v' "}'
$  123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1:             ^ unexpected newline or end of string 

これには戸惑ってしまいます。




Answer 1 Jotne


シェル変数を awk に取り込む

いくつかの方法で行うことができます。いくつかは他よりも優れています。これはそれらのほとんどをカバーするはずです。コメントがあれば下に書いてください。v1.5


-v の使用 (最善の方法、最も移植性の高い)

-v オプションを使用します(PSは -v の後にスペースを使用します。そうしないと移植性が低下します。たとえば、 awk -v var=awk -vvar= はありません)

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

これはほとんどの awk と互換性があり、変数は BEGIN ブロックでも使用できます。

複数の変数がある場合

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

警告。エド・モートンが書いているように、エスケープシーケンスは、そのように解釈されます \t 実数になり tab ではなく \t それはあなたが検索するものである場合。 ENVIRON[] を使用して解決するか、 ARGV[] 介してアクセスできます

PSセパレータとして3つの縦棒が必要な場合 ||| 、エスケープできないため、 -F"[|][|][|]"

プログラム/関数innから awk にデータを取得する例(ここでは日付が使用されています)

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

コードブロック後の変数

ここでは、 awk コードの後に変数を取得します。 BEGIN ブロックで変数を必要としない限り、これは問題なく機能します。

variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
  • 複数の変数を追加します。

awk '{print a,b,$0}' a="$var1" b="$var2" file

  • このようにして、ファイルごとに異なるフィールドセパレータ FS を設定することもできます。

awk 'some code' FS=',' file1.txt FS=';' file2.ext

  • コードブロックの後の変数は、 BEGIN ブロックでは機能しません。

echo "input data" | awk 'BEGIN {print var}' var="${variable}"


Here-string

変数は、それらをサポートするシェル(bashを含む)のhere-stringを使用して awk に追加することもできます。

awk '{print $0}' <<< "$variable"
test

と同じです。

printf '%s' "$variable" | awk '{print $0}'

追伸:この変数はファイル入力として扱われます。


ENVIRON 入力

TrueYが書いているように、 ENVIRON を使用して環境変数を出力できます。AWKを実行する前に変数を設定すると、次のように出力できます。

X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash

ARGV 入力

Steven Pennyが書いているように、 ARGV を使用してデータをawkに取り込むことができます。

v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data

BEGINだけではなく、コード自体にデータを取り入れること。

v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test

コード内の変数。注意して使用してください

awk コード内で変数を使用できますが、乱雑で読みにくいため、 Charles Duffy が指摘しているように、このバージョンもコードインジェクションの犠牲になっている可能性があります。誰かが変数に悪いものを追加すると、それは awk コードの一部として実行されます。

これは、コード内の変数を抽出することで動作するので、コードの一部になります。

変数を使用して動的に変化する awk を作成する場合は、この方法で実行できますが、通常の変数には使用しないでください。

variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two

コードインジェクションの例です。

variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000

この方法で多くのコマンドを awk に追加できます。無効なコマンドでクラッシュすることさえあります。


追加情報です。

ダブルクォートの使用

変数 "$variable" を二重引用符で囲むのは常に良いことです
そうでない場合は、複数行が長い1行として追加されます。

Example:

var="Line one
This is line two"

echo $var
Line one This is line two

echo "$var"
Line one
This is line two

他にもダブルクォートをしなくても得られるエラーがあります。

variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1:    ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1:    ^ syntax error

また、シングルクォートでは、変数の値を展開しません。

awk -v var='$variable' 'BEGIN {print var}'
$variable

AWKと変数の詳細情報

このFAQを読んでください




Answer 2 TrueY


古き良き ENVIRON awkの組み込みハッシュについてはまったく触れられていないようです。その使用例:

$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt



Answer 3 Ed Morton


処理するシェル変数でのバックスラッシュの扱い方に応じて、これらのいずれかを使用します( avar はawk変数、 svar はシェル変数です)。

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

詳細およびその他のオプションについては、http://cfajohnson.com/shell/cus-faq-2.html#Q24を参照してください。上記の最初の方法は、ほとんど常に最良のオプションであり、最も明白なセマンティクスを持っています。




Answer 4 Johnsyweb


環境変数( "${v}" )の変数名( v )と値( = )を指定して、コマンドラインオプション -v を渡すことができます。

% awk -vv="${v}" 'BEGIN { print v }'
123test

または、それをより明確にするため( v がはるかに少ない):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test



Answer 5 Steven Penny


ARGVを利用することができます。

v=123test
awk 'BEGIN {print ARGV[1]}' "$v"

体内に続ける場合は、ARGCの調整が必要になるので注意してください。

awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"