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를 분석하여 다른 두 개와 구별해야 합니다. 이는 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), 이것이 "파일을 찾을 수 없음" 오류가 발생하는 이유입니다.