awk 스크립트에 매개변수 전달

awk 스크립트에 매개변수 전달

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가 스크립트 본문에 도달하는 순간 BEGINARGV[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), 이것이 "파일을 찾을 수 없음" 오류가 발생하는 이유입니다.

관련 정보