外部のシェル変数を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[]
経由でアクセスすることで解決できます
ここで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
でも動作します
このように変数を使用しても、BEGIN
ブロックでは機能しません。
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
それらをサポートするシェル(/ bashを含む)から here-string を使用して、変数をawk
に追加することもできます。
awk '{print $0}' <<< "$variable"
test
これは以下と同じです。
printf '%s' "$variable" | awk '{print $0}'
P.Sこれは変数をファイル入力として扱います。
ENVIRON
入力TrueYが書いているように、ENVIRON
を使って 環境変数 を表示することができます。 AWKを実行する前に変数を設定すると、次のように出力できます。
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["Shell"]}'
MyVar /bin/bash
ARGV
入力Steven Pennyが書いているように、データをawkに入れるためにARGV
を使うことができます。
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"
を二重引用符で囲むのは常に良いことです。
そうでなければ、複数の行が長い単一行として追加されます。
例:
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
古き良きENVIRON
awk 組み込みハッシュはまったく言及されていないようです。その使用例
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
シェル変数のバックスラッシュの扱い方に応じて、これらのいずれかを使用します(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 を参照してください。上記の最初の方法はほとんど常にあなたの最良の選択肢であり、最も明白な意味論を持っています。
コマンドラインオプション-v
に、変数名(v
)と環境変数(=
)の値("${v}"
)を指定して渡すことができます。
% awk -vv="${v}" 'BEGIN { print v }'
123test
もっと明確にするには(はるかに少ないv
sで):
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
あなたはARGVを利用することができます:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
あなたが身体の中に続けようとしているならば、あなたはARGCを調整する必要があるでしょう:
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
ログファイルの行の先頭に日付を挿入する必要があり、それは以下のように行われます。
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
保存するために別のファイルにリダイレクトすることができます
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
@ Jotneの答えを「for loop」に変更しただけです。
for i in `seq 11 20`; do Host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done