N引数をstdinに渡し、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
しかし、これは少し制限的で長いです。私はこれをシェルスクリプトでラップすることができることを知っていますが、私が持っているものを似たようなものに含めるためのきちんとした方法があるかどうかはわかりません。
答え1
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
$
答え2
ただの楽しみで(これは確かに推奨されるアプローチではありません):awk
「位置パラメータ」(PP)は知らず、変数の割り当てと入力ファイル名だけがわからないため、PPを分析して他の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に入力をパイプする場合は、トークンを省略してリストの最後までPPを取得できます(つまり、トークンを ""に設定)。
答え3
あなたはすでにこれを知っています-v variable=value
。別の方法は、環境を介して変数を渡して配列から読み取ることですENVIRON
。
$ var1=hello var2=world awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world
var1
これは環境でのみvar2
環境変数を設定します。awk
または、
$ export var1=hello var2=world
$ awk 'BEGIN { print ENVIRON["var1"], ENVIRON["var2"] }'
hello world
これは、呼び出し前に呼び出し環境の変数を設定しますawk
。
配列には、プログラムが順次読み取るファイル名のみが含まれますが、ARGV
次のようにコマンドラインで設定された変数名も含めることができます。awk
awk '...' var1=value1 var2=value2 filename
これは一般的にいいえ変数を渡すための推奨方法(たとえば、awk
これらの変数はブロックでは使用できません)BEGIN
答え4
次のスクリプトを作成できます。
#!/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=...
here-docを介して実際のawkプログラムに渡しますawk
(もちろん、awkスクリプトを別のファイルに入れることができます)。ただし、この方法では入力ファイルの名前を渡すことはできず、stdinからawkスクリプトを読む必要があります。
少なくともGNU awkは、ARGV[n]
入力ファイルとして使用される内容を明確に文書化します(https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html)、これが「ファイルが見つかりません」エラーが発生する理由です。