357

外部シェル変数をスクリプトに渡す方法をいくつか見つけましたが、と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 

私はこれについて混乱しています。

4

9 に答える 9

592

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


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

-vオプションを使用してください: (PS の後にスペースを使用し-vないと、移植性が低下します。例: awk -v var=not 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}"


ヒアストリング

変数は、それらをサポートするシェル (Bash を含む) からヒア文字列awkを使用して追加することもできます。

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

これは次と同じです。

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

PSこれは変数をファイル入力として扱います。


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。無効なコマンドでクラッシュさせることさえできます。

ただし、このアプローチの有効な使用方法の 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 スクリプトのテキストの一部にする必要があります。


追加情報:

二重引用符の使用

変数を二重引用符で囲むことは常に良いことです"$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 と変数に関する詳細情報

このよくある質問をお読みください

于 2013-09-29T07:51:52.967 に答える
31

古き良きENVIRON 組み込みハッシュはまったく言及されていないようです。使用例:

$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
于 2014-11-06T12:46:34.050 に答える
14

シェル変数でバックスラッシュを処理する方法に応じて、次のいずれかを使用します (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を参照してください。上記の最初の方法は、ほとんどの場合、最良の選択肢であり、最も明白なセマンティクスを備えています。

于 2013-09-29T13:22:50.273 に答える
10

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

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

または、より明確にするために(はるかに少ないvs で):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
于 2013-09-29T07:49:33.183 に答える
0

ログ ファイルの行の先頭に日付を挿入する必要がありましたが、次のようにします。

DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log

別のファイルにリダイレクトして保存できます

于 2016-03-02T08:07:01.883 に答える