다음과 같은 최소한의 예가 있습니다 awk
.
#!/usr/bin/awk -f
BEGIN {
if (ARGC>1)
a=ARGV[1]
else
a=5
}
{
print
}
으로 호출하면 다음 ls -l|./t.awk
이 생성됩니다.
$ ls -l|./t.awk 2
awk: ./t.awk:4: fatal: cannot open file `2' for reading (No such file or directory)
Argument() 없이 호출하면 ls -l|./t.awk
문제가 없습니다.
그래서 첫 번째 질문은 단순한 문자열 동일성 검사 대신 "2"라는 파일을 읽으려고 한다는 것입니다.
두 번째 놀라운 점은 두 번째 블록을 제거하면 제대로 작동한다는 것입니다! (빈 출력을 제공합니다.)
#!/usr/bin/awk -f
BEGIN {
if (ARGC>1)
a=ARGV[1]
else
a=5
}
이유는 무엇입니까?
답변1
awk는 매개변수를 제공하지만 궁극적으로 원하는 대로 매개변수를 조작할 수 있습니다. 예를 들어, arg를 공백으로 설정하면 됩니다.
if (ARGC>1) {a=ARGV[1]; ARGV[1]=""}
else a=5
그렇지 않으면 args는 옵션이 아닌 항목에 대한 입력 파일 이름인 일반 기능을 갖습니다. 따라서 awk는 "2" 파일을 읽고 그 파일에서 스크립트 본문을 실행하려고 시도합니다.
답변2
명령줄에서 awk에 인수를 전달하면 awk는 파일을 제공한다고 가정하여 해당 파일을 열려고 시도합니다. 나는 당신이 무슨 일이 일어나기를 기대하는지 정말로 이해하지 못합니다. 이것이 awk가 일반적으로 행동하는 방식입니다.
제거하면 작동하는 이유 { print }
도 간단합니다. 이를 제거하면 BEGIN{}
입력 파일을 읽기 전에 실행되는 단일 블록이 남습니다 . 그 외에는 아무것도 없기 때문에 BEGIN{}
파일을 읽으려고 할 이유가 없으며 프로그램이 종료됩니다. 이는 다음을 통해 쉽게 확인할 수 있습니다 strace
.
$ strace awk 'BEGIN{a=1}{print}' somefile |& grep 'open.*somefile'
openat(AT_FDCWD, "somefile", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "cannot open file `somefile' for "..., 66cannot open file `somefile' for reading: No such file or directory) = 66
위 내용을 다음과 비교해보세요.
$ strace awk 'BEGIN{a=1}' somefile |& grep 'open.*somefile'
$
파일에 대해 어떤 작업도 수행할 필요가 없으므로 파일을 열려고 시도하지 않습니다.
당신이 찾고 있는 것은 foo=bar
명령줄에서 변수를 전달할 수 있는 형식이라고 생각합니다.
ls -l|./t.awk a=2
다음으로 스크립트를 다음과 같이 변경합니다.
#!/bin/awk -f
BEGIN {
if (!a){
a=5
}
}
{
print a,$0
}
그리고 그것이 어떻게 작동하는지 설명하세요:
$ echo foo | t.awk ## default value
5 foo
$ echo foo | foo.awk a=12 ## value given at launch
12 foo
또는 이 옵션을 사용하여 명령줄에서 직접 실행할 때 -v
동일한 작업을 수행 할 수 있습니다.
$ awk -v a=12 'BEGIN{print a}'
12