N個の引数を渡してstdinから読み取れるようにしたいawkスクリプトがあります。私は次のようなことができるようになりたいです
tail -f logfile | my_cool_awk_scipt var1 var2 var3 ... varN
そして、これらの変数をスクリプト内で使用します。
#!/bin/awk -f
BEGIN {
print "AWK Script Starting"
print ARGV[1]
}
{
if ($0 < ARGV[1])
print $0
else if ($0 < ARGV[2])
print $0 + ARGV[2]
}
そのまま変数を渡そうとすると、ARGV[1]
そしてヒット
awk: ./my_cool_awk_script:4: fatal: cannot open file `var1' for reading (No such file or directory)
できます、
tail -f logfile | my_cool_awk_scipt -v var1=var1 -v var2=var2 -v var3=var3 ... varN=varN
しかし、これは少し制限的で冗長です。私はこれをシェルスクリプトでラップすることもできますが、私が持っているものをそのようなものに埋め込むクリーンな方法がわかりません。
よろしくお願いします。
Awkがスクリプトの本体に到達した瞬間、BEGIN
の後に、ARGV [x]で指定されたファイル名を読み取ります。だから核兵器だけ。
$ cat a.awk
#!/bin/awk -f
BEGIN {
print "AWK Script Starting"
ZARGV[1]=ARGV[1]
ZARGV[2]=ARGV[2]
ARGV[1]=""
ARGV[2]=""
}
{
if ($0 < ZARGV[1])
print $0
else if ($0 < ZARGV[2])
print $0 + ZARGV[2]
}
$
例:
$ cat logfile
1
2
3
4
5
$ ./a.awk 3 4 <logfile
AWK Script Starting
1
2
7
$
それを楽しむためだけに(そしてこれは確かには推奨される方法ではありません):awk
は「位置パラメータ」(PP)を認識せず、変数の割り当てのみを認識しますファイル名を入力し、PP outを分析して他の2つから区別する必要があります。これは、PPを固定トークンで分離することで実行できます。 、例えば--
(他のコンテキストでも使用されます)、またはPPカウント、固定またはARGV [1]などで伝達される)を知ることにより。試す
awk '
BEGIN {while (ARGV[++MXPP] != "--") PP[MXPP] = ARGV[MXPP]
for (j=MXPP+1; j<ARGC; j++) ARGV[j-MXPP] = ARGV[j]
ARGC -= --MXPP
}
{if ($0 < ARGV[1])
print $0
else if ($0 < ARGV[2])
print $0 + ARGV[2]
}
' VAR1 VAR2 -- file[12]
入力ファイルの代わりにstdinを使用してsthをパイプする場合、トークンを省略して、リストの最後までPPをフェッチすることができます(つまり、トークンを ""に設定します)。
あなたはすでに-v variable=value
について知っています。もう1つの方法は、変数を環境に渡し、ENVIRON
配列から読み取ることです。
$ var1=hello var2=world awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world
これにより、awk
の環境でのみ環境変数var1
およびvar2
が設定されます。
または、
$ export var1=hello var2=world
$ awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world
これにより、awk
を呼び出す前に、呼び出し環境で変数が設定されます。
ARGV
配列には、awk
プログラムが順番に読み取るファイル名のみが含まれますが、次のようにコマンドラインで設定された変数名が含まれる場合もあります。
awk '...' var1=value1 var2=value2 filename
これは一般的にnotですが、変数をawk
に渡す方法として推奨されます(これらの変数は、たとえばBEGIN
ブロックでは使用できません)。
次のようなスクリプトを作成できます。
#!/bin/bash
vars=()
i=1
for arg in "$@"; do
vars+=(-v "var$i=$arg")
i=$((i+1))
done
awk "${vars[@]}" -f/dev/fd/3 3<< EOF
BEGIN {
printf "awk var1: %s\n", var1;
printf "awk var2: %s\n", var2;
}
1
EOF
そしてそれを実行します:
$ echo some input | ./awk.sh foo bar doo
awk var1: foo
awk var2: bar
some input
シェルスクリプトはそれらのコマンドラインを構築します-v var1=...
引数、およびそれらをawk
に、実際のawkプログラムとともにhere-docを介して渡します(もちろん、代わりにawkスクリプトを別のファイルに含めることもできます)。この方法で入力ファイルの名前を渡すことはできませんが、awdスクリプトをstdinから読み込ませる必要があります。
少なくともGNU awkはARGV[n]
も入力ファイルとして使用されます( https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html )。これが、 「ファイルが見つかりません」エラー。