1. ホーム
  2. バッシュ

[解決済み] [Solved] awk スクリプトでシェル変数を使うには?

2022-05-03 13:15:55

質問

外部シェル変数を 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 

これには困りましたね。

どのように解決するのですか?

<ブロッククオート

#シェル変数の取得 awk は、いくつかの方法で行うことができます。いくつかの方法は、他の方法よりも優れています。これはそのほとんどをカバーするはずです。 もし、コメントがあれば、下に残してください。


使用方法 -v (最も良い方法、最もポータブルな方法)

を使用します。 -v オプション: (P.S.) -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}'

警告 . Ed Morton が書いているように、エスケープシーケンスは次のように解釈されます。 \t は本当の tab であって \t を検索してください。を使用することで解決できます。 ENVIRON[] を経由してアクセスするか ARGV[]

PS 3本の縦棒をセパレータとして使用する場合 ||| を使用すると、エスケープすることができません。 -F"[|][|][|]"

<ブロッククオート

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

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

シェル変数の内容を正規表現でテストする例です。

awk -v var="$variable" '$0 ~ var{print "found it"}'


コードブロックの後の変数

の後に変数を取得します。 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}"


ここに文字列

また、変数は awk を使用しています。 ここで文字列 をサポートするシェル(Bashを含む)から入手できます。

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 入力

スティーブン・ペニー氏が書いているように 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 このように 有効でないコマンドでクラッシュさせることもできます。

しかし、この方法の有効な使い方のひとつは、単純な計算機のような入力に対して適用されるシンボルを awk に渡したい場合です。

$ calc() { awk -v x="$1" -v z="$3" 'BEGIN{ print x '"$2"' z }'; }

$ calc 2.7 '+' 3.4
6.1

$ calc 2.7 '*' 3.4
9.18

シェル変数の値を代入した awk 変数を使ってこれを行う方法はありません。awk が解釈する前に、シェル変数を展開して awk スクリプトのテキストの一部とする必要があります。


おまけ情報

ダブルクォートの使用

変数のダブルクォートは常に有効です。 "$variable"

そうでない場合は、複数の行が長い一行として追加されます。

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を読む .