外部シェル変数をスクリプトに渡す方法をいくつか見つけましたが、と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
これについては混乱しています。
ベストアンサー1
#シェル変数を取得するには
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}'
警告。Ed Morton が書いているように、また上記の例に見られるように、シェル変数は awk が内容を と見なす前にシェルによって展開され、awk -v var='line one\nline two'
したがって、そのシェル変数の内容にあるエスケープ シーケンスは を使用すると解釈されます-v
。これは、awk で文字列を変数に割り当てる他のすべての形式 (例:awk 'BEGIN{var="line one\nline two"} {...}'
または )の場合と同様です。awk '{...}' var='line one\nline two'
したがって、 は\n
リテラルな LineFeed 文字になり、2 文字の文字列 にはなりません\n
。たとえば、次のような変数があるとします。
$ variable='a\tb\n$c\kd'
awk は割り当て内のエスケープ シーケンスを展開します。
$ awk -v var="$variable" 'BEGIN{ printf "%s\n", var }'
awk: warning: escape sequence `\k' treated as plain `k'
a b
$ckd
それが望ましくない場合、シェル (例bash
) とロケール (例LC_ALL=C
) がこれをサポートしていれば、シェル パラメータ置換を使用してバックスラッシュをエスケープすることで、バックスラッシュを文字どおりに扱うことができます。
$ awk -v var="${variable//\\/\\\\}" 'BEGIN{ printf "%s\n", var }'
a\tb\n$c\kd
または、(下記参照)を使用しENVIRON[]
てアクセスすることもできます。ARGV[]
-v var="$(printf '%q' "$variable")"
これも s をエスケープするため、 for は使用できません。また、 sを追加するだけなので、$
も使用できず、エスケープ シーケンスは awk によって解釈されます。これは、これら 2 つのアプローチはどちらも、文字列を変数に割り当てる awk 構文ではなく、コマンド入力を提供するためのシェル構文に従って文字をエスケープするためです。-v var="${variable@Q}"
'
"$variable"
PS縦棒やその他の正規表現メタ文字を区切り文字として使用する場合は|?(
、二重にエスケープする必要があります。例 3 の縦棒|||
は になります-F'\\|\\|\\|'
。 を使用することもできます-F"[|][|][|]"
。
プログラム/関数からデータを取得する例
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
これは以下と同じです:
echo "$variable" | awk '{print $0}'
printf '%s' "$variable" | awk '{print $0}'
PS これは変数をファイル入力として扱います。
ENVIRON
入力
TrueY が書いているように、 を使用して環境変数ENVIRON
を印刷できます。AWK を実行する前に変数を設定すると、次のように印刷できます。
export X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
またはエクスポートされていない変数の場合:
x=MyVar
x="$x" awk 'BEGIN{print ENVIRON["x"],ENVIRON["SHELL"]}'
MyVar /bin/bash
ARGV
入力
ARGV
Steven Penny が書いているように、データを 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
。無効なコマンドでクラッシュさせることもできます。
ただし、このアプローチの有効な使用法の 1 つは、たとえば単純な計算機などの入力に適用するシンボルを 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 スクリプトのテキストの一部になるように展開される必要があります。(Ed M. による以下のコメントを参照してください。)
追加情報:
二重引用符の使用
変数を二重引用符で囲むのは常に良いことです。"$variable"
そうしないと、複数行が長い 1 行として追加されます。
例:
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