awk 'processing_script_here' my=file.txt
끝없이 멈추고 기다리는 것...
여기서 무슨 일이 일어나고 있으며 어떻게 작동하게 만들까요?
답변1
~처럼크리스가 말한다, 양식의 인수는 입력 파일 이름이 아닌 변수 할당(문 이전에 수행되는 (최신) 변수 할당 variablename=anything
과 달리 인수가 처리될 때 수행됨)로 처리됩니다 .-v var=value
BEGIN
이는 다음과 같은 경우에 유용합니다.
awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2
FS
거기에서 파일 별로 서로 다른 것을 지정할 수 있습니다 RS
. 또한 일반적으로 다음 용도로 사용됩니다.
awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2
더 안전한 버전은 다음과 같습니다.
awk 'NR==FNR{a[$0]; next}; {...}' file1 file2
file1
(비어 있으면 아무런 효과가 없습니다)
=
그러나 파일 이름에 문자가 포함되어 있으면 문제가 발생합니다.
=
이제 이것은 첫 번째 남은 내용이 유효한 변수 이름인 경우에만 문제가 됩니다 awk
.
에서는 유효한 변수 이름의 구성이 awk
에서보다 더 엄격합니다 sh
.
POSIX에서는 다음과 같아야 합니다.
[_a-zA-Z][_a-zA-Z0-9]*
이식 가능한 문자 세트의 문자만 사용하십시오. 그러나 /usr/xpg4/bin/awk
Solaris 11은 최소한 이 점에서 호환되지 않으며 a-zA-Z뿐만 아니라 로케일의 모든 알파벳 문자를 변수 이름에 사용할 수 있습니다.
x+y=foo
따라서 =bar
or 또는 같은 인수는 ./foo=bar
여전히 할당이 아닌 입력 파일 이름으로 처리됩니다. 첫 번째 인수의 나머지 부분은 =
유효한 변수 이름이 아니기 때문입니다. 구현 및 로캘 Stéphane=Chazelas.txt
에 따라 "may" 또는 "not"과 같은 매개변수입니다 .awk
그렇기 때문에 awk를 사용할 때 다음을 사용하는 것이 좋습니다.
awk '...' ./*.txt
바꾸다
awk '...' *.txt
예를 들어, 파일 이름에 문자가 txt
포함되지 않는다고 보장할 수 없는 경우 문제를 방지할 수 있습니다 =
.
또한 다음을 -vfoo=bar.txt
사용하는 경우 유사한 매개변수가 옵션으로 간주될 수 있습니다.
awk -f file.awk -vfoo=bar.txt
(1.28.0 이전의 busybox 버전에도 적용 가능합니다 awk '{code}' -vfoo=bar.txt
.awk
해당 오류 보고서).
다시 말하지만, ./*.txt
이 문제는 다음을 사용하여 해결할 수 있습니다(접두사를 사용하면 다른 의미로 이해되는 ./
파일을 호출할 때도 도움이 됩니다).-
awk
표준 입력대신에).
이는 이유
#! /usr/bin/awk -f
Shebangs는 실제로 작동하지 않습니다. 이러한 문제는 var=value
다음을 통해 해결될 수 있지만고정명세서의 값 ARGV
( ./
접두사 추가) BEGIN
:
#! /usr/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++)
if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
ARGV[i] = "./" ARGV[i]
}
# rest of awk script
이는 옵션에 도움이 되지 않습니다. 왜냐하면 해당 옵션은 스크립트 awk
가 아닌 awk
스크립트에 의해 표시되기 때문입니다.
이 접두사 사용 시 ./
발생할 수 있는 외관상의 문제 중 하나 는 로 끝나는 것입니다. 그러나 원하지 않는 경우 FILENAME
언제든지 이 접두사를 사용하여 제거할 수 있습니다.substr(FILENAME, 3)
GNU 구현은 awk
옵션을 통해 이러한 모든 문제를 해결합니다 -E
.
그 후 -E
gawk는 스크립트 경로 awk
( -
여전히 stdin을 의미함)와 입력 파일 경로 목록만 예상합니다( -
특별한 처리도 수행하지 않음).
이는 다음을 위해 설계되었습니다:
#! /usr/bin/gawk -E
인수 목록이 항상 입력 파일인 shebangs( ARGV
명령문 내에서 목록을 자유롭게 편집 할 수 있다는 점에 유의하세요 BEGIN
).
다음과 같이 사용할 수도 있습니다.
gawk -e '...awk code here...' -E /dev/null *.txt
후속 스크립트가 문자를 포함하더라도 항상 입력 파일로 처리되도록 하기 위해 -E
빈 스크립트( )를 사용합니다 ./dev/null
*.txt
=
답변2
대부분의 awk 버전에서 실행될 프로그램 뒤에 오는 매개변수는 다음과 같습니다.
- 하나의 문서
- 테이블 할당
x=y
파일 이름은 사례 #2로 해석되므로 awk는 여전히 stdin에서 무언가를 읽기를 기다리고 있습니다(파일 이름이 전달된 것을 감지하지 못하기 때문입니다).
이식 가능하게도 이 동작은POSIX에 문서화됨:
다음 두 가지 유형의 매개변수를 혼합할 수 있습니다.
- 파일: 프로그램에 설정된 패턴과 일치하도록 읽어야 할 입력이 포함된 파일의 경로 이름입니다. 파일 피연산자가 지정되지 않거나 파일 피연산자가 "-"인 경우 표준 입력을 사용해야 합니다.
- 할당: 이식 가능한 문자 집합의 밑줄 또는 알파벳 문자로 시작하는 피연산자(IEEE Std 1003.1-2001, 섹션 6.1 이식 가능한 문자 집합의 기본 정의 볼륨에 있는 표 참조), 그 뒤에 일련의 밑줄, 숫자가 옵니다. 및 "=" 문자가 뒤따르는 이식 가능한 문자 집합의 문자는 경로 이름이 아닌 변수 할당을 지정해야 합니다.
따라서 몇 가지 이식 가능한 옵션이 있습니다(#1이 아마도 가장 덜 방해가 될 것입니다).
- "이식 가능한 문자 집합의 밑줄 또는 알파벳 문자"가 아니기
awk ... ./my=file
때문에 이를 회피하는 를 사용하세요 ..
- 표준 입력에 파일을 배치하는 데 사용됩니다
awk ... < my=file
. 그러나 이는 여러 파일에서는 제대로 작동하지 않습니다. - 임시로 파일에 대한 하드 링크를 만든 다음 사용하세요. 이와 같은 작업을 수행
ln my=file my_file
하고my_file
정상적으로 사용할 수 있습니다. 복사는 수행되지 않으며 두 파일 모두 동일한 데이터 및 inode 메타데이터로 백업됩니다. 사용 후에는 해당 아이노드에 대한 참조 개수가 여전히 0보다 크기 때문에 생성된 링크를 삭제해도 안전합니다.
답변3
견적으로 이동멍청한 문서(추가 강조 사항 참고):
명령줄의 다른 인수는 일반적으로 지정된 순서대로 처리되는 입력 파일로 처리됩니다. 하지만,var=value 형식의 매개변수는 var 변수에 값을 할당하며 파일을 전혀 지정하지 않습니다.
명령이 중지되고 기다리는 이유는 무엇입니까? 형태로 있기 때문에awk 'processing_script_here' my=file.txt
지정된 파일이 없습니다.위의 정의에서 - my=file.txt
는 변수 할당으로 해석되며 파일이 정의되지 않은 경우 stdin을 읽습니다( 이러한 명령의 awk가 시스템 호출을 기다리고 있다는 것도 awk
분명합니다 .strace
read(0,'...)
이 내용은 에도 기록되어 있습니다.POSIX awk 사양, 피연산자 섹션 및작업그것의 일부)
awk '{print foo}' foo=bar /etc/passwd
/etc/passwd의 각 줄이 값을 인쇄하기 때문에 변수 할당은 분명합니다 . 그러나 경로나 전체 경로를 foo
지정하면 작동합니다../foo=bar
실행 strace
하고 awk '1' foo=bar
확인 하면 cat foo=bar
이것이 awk 특정 문제임을 알 수 있으며 execve는 파일 이름을 전달된 인수로 표시하므로 이 경우 쉘은 환경 변수 할당과 아무 관련이 없습니다.
awk '...script...' foo=bar
또한 환경 변수 할당은 명령 전에 적용되어야 하므로 이로 인해 쉘이 환경 변수를 생성하지 않습니다. 바라보다POSIX 쉘 구문 규칙, 포인트 7. 추가적으로 이는 다음을 통해 확인할 수 있습니다.awk '{print ENVIRON["foo"]}' foo=bar /etc/passwd