awk 'processing_script_here' my=file.txt
무기한으로 멈추고 기다릴 것 같습니다 ...
여기서 무슨 일이 일어나고 있으며 어떻게 작동합니까?
awk 'processing_script_here' my=file.txt
무기한으로 멈추고 기다릴 것 같습니다 ...
여기서 무슨 일이 일어나고 있으며 어떻게 작동합니까?
답변:
로 크리스는 말한다 , 형태의 인수 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
또는이 ./foo=bar
무엇을하는 것은의 남아로 여전히 입력 파일 이름이 아닌 과제로 처리됩니다 첫번째 =
유효한 변수 이름이 아닙니다. 구현 및 로케일 Stéphane=Chazelas.txt
에 따라 같은 인수가 있을 수도 있고 아닐 수도 있습니다 awk
.
그래서 awk에서는 다음을 사용하는 것이 좋습니다.
awk '...' ./*.txt
대신에
awk '...' *.txt
예를 들어 txt
파일 이름에 =
문자 가 포함되어 있지 않다고 보장 할 수없는 경우 문제를 피하기 위해 .
또한 -vfoo=bar.txt
다음을 사용하는 경우 와 같은 인수 가 옵션으로 취급 될 수 있습니다.
awk -f file.awk -vfoo=bar.txt
(또한 적용 awk '{code}' -vfoo=bar.txt
와 awk
비지 버전 1.28.0 사전을 참조 버그 리포트에 대응 ).
다시 말하지만, 그 문제를 ./*.txt
해결하면 ./
접두사를 사용하면 표준 입력 을 의미 -
하는 것으로 awk
이해 되는 파일이 도움이 됩니다.
그 이유도
#! /usr/bin/awk -f
shebangs는 실제로 작동하지 않습니다. 그동안 var=value
사람에 의해 해결할 수있는 고정ARGV
값 (A 추가 ./
A의 접두사를) 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
A의 목록 BEGIN
문).
다음과 같이 사용할 수도 있습니다.
gawk -e '...awk code here...' -E /dev/null *.txt
우리는 사용 -E
빈 스크립트 (로 /dev/null
단지 있는지 그 수 있도록) *.txt
가 포함 된 경우에도, 그 후에는 항상 입력 파일로 취급되는 =
문자.
../foo
, /path/to/foo
경우에하는 - 다른 인코딩에있는 경로) substr(FILENAME,3)
충분하지 않을 것이다, 또는 그것의 사용자가 기본적으로 파일 이름이 무엇인지 알고있는 원샷 스크립트 –이 경우 아마도 =
;-)를 포함하는 파일을 신경 쓰지 않아야 합니다.
./
문제 라고 너무 많이 말하지는 않지만 파일 이름이 출력에 포함 ./
되어야 하는 경우와 같이 특정 조건에서는 바람직 하지 않을 수 있다고 생각합니다 .이 경우 중복되고 불필요해야합니다. 어떻게 든 그것을 제거해야합니다. 최소한 하나의 예가 있습니다. 사용자는 파일 이름이 무엇인지 알고 있습니다.이 경우 파일 이름이 무엇인지 알지만 =
여전히 적절한 처리를 방해합니다. 따라서지도가 -
방해받을 수 있습니다 .
./
접두사 를 사용하여 해당 awk
기능 을 해결하고 싶지만 ./
출력에서 출력을 제거하려고합니다. 파일의 첫 줄에 특정 문자열이 포함되어 있는지 확인하는 방법을 참조하십시오 . 예로서.
./
하는 전역 (절대 경로)이기도 /
합니다.
대부분의 awk 버전에서 프로그램이 실행 한 후의 인수는 다음 중 하나입니다.
x=y
파일 이름이 사례 # 2로 해석되고 있기 때문에 awk는 stdin에서 읽을 내용을 계속 기다리고 있습니다 (파일 이름이 전달 된 것으로 인식하지 못하기 때문에).
이 동작은 POSIX에 문서화되어 있습니다 .
다음 두 가지 유형의 인수를 혼합 할 수 있습니다.
- file : 읽을 입력이 포함 된 파일의 경로 이름으로, 프로그램의 패턴 세트와 일치합니다. 파일 피연산자가 지정되지 않았거나 파일 피연산자가 '-'인 경우 표준 입력이 사용됩니다.
- 할당 : 휴대용 문자 집합에서 밑줄 또는 영문자로 시작하는 피연산자 (IEEE Std 1003.1-2001의 기본 정의 볼륨, 6.1, 휴대용 문자 집합의 표 참조) 뒤에 밑줄, 숫자, 휴대용 문자 집합의 알파벳 문자와 '='문자는 경로 이름 대신 변수 할당을 지정해야합니다.
따라서, 몇 가지 옵션이 있습니다 (# 1은 가장 방해가되지 않습니다).
awk ... ./my=file
때문에이를 회피하는을 사용하십시오 .
.awk ... < my=file
. 그러나 이것은 여러 파일에서 제대로 작동하지 않습니다.ln my=file my_file
한 다음 my_file
정상적으로 사용할 수 있습니다 . 복사가 수행되지 않으며 두 파일 모두 동일한 데이터와 inode 메타 데이터로 백업됩니다. 사용 후에는 inode에 대한 참조 수가 여전히 0보다 커서 생성 된 링크를 제거하는 것이 안전합니다../my=file
작동 하지 않습니까? 유효한 변수 이름이 아니기 % awk 'processing_script_here' ./my=file.txt awk: fatal: cannot open file ./my=file.txt' for reading (No such file or directory).
때문에 이식성이 뛰어나므로 ./my
그렇게 해석해서는 안됩니다.
=
앞에 휴대용 문자 세트의 밑줄 또는 알파벳 문자가 오는 경우에만 발생합니다 (IEEE Std 1003.1-2001의 기본 정의 볼륨, 6.1, 휴대용 문자 세트의 표 참조). 휴대용 문자 집합에서 밑줄, 숫자 및 알파벳 순서가 이어집니다 . 그래서 파일과 같은 경로 ++foo=bar.txt
나 =foo
또는 ./foo=bar
그 모든 OK입니다 .
또는 +
하지 않은 것입니다 [_a-zA-Z]
.
./my=file
그대로 전달됩니다.
awk '{print $1,$2}' /etc/passwd
. 요점은 awk와 달리 셸에서 파일을 여는 것이 파일을 찾을 수 있는지 여부와는 아무런 차이가 없다는 것입니다. 실제로에서에서 첫 번째 레코드의 끝까지 되돌아 가서 stdin 내의 위치를 벗어나지 않도록 awk '{exit}' < /etc/passwd
기대할 awk
수 exit
있습니다. POSIX가 필요합니다. /usr/xpg4/bin/awk
솔라리스에서는 이 작업을 수행하지만 GNU / Linux에서는 그렇게 하지 gawk
않습니다 mawk
.
awk
그런 식으로 식별 된 위치 .
gawk 문서 를 인용하려면 (참고 강조 사항 추가) :
명령 행의 추가 인수는 일반적으로 지정된 순서대로 처리 할 입력 파일로 처리됩니다. 그러나 var = value 형식의 인수는 값을 변수 var에 지정합니다. 파일을 전혀 지정하지 않습니다.
왜 명령이 멈추고 기다 립니까? 양식 에 위의 정의에 의해 awk 'processing_script_here' my=file.txt
지정된 파일이 없기my=file.txt
때문에 변수 할당으로 해석되며, 정의 된 파일이 없으면 awk
stdin을 읽을 것입니다 (이 strace
명령의 awk가 read(0,'...)
syscall을 기다리고 있음을 나타냅니다) .
이것도 POSIX awk 사양에 문서화되어 있습니다. OPERANDS 섹션과 그 할당 부분을 참조하십시오 )
변수 할당은 / etc / passwd의 모든 행에 대해 awk '{print foo}' foo=bar /etc/passwd
값 foo
이 인쇄 된다는 점 에서 분명 합니다. ./foo=bar
그러나 지정 하거나 전체 경로가 작동합니다.
참고 실행 strace
에 awk '1' foo=bar
뿐만 아니라 함께 확인 cat foo=bar
이 AWK-특정 문제이며, 인수가 전달로 포탄이 경우 ENV 변수 할당과는 아무 상관이없는, 그래서는 execve는, 쇼 파일 이름을한다는 것을 보여줍니다.
또한 awk '...script...' foo=bar
환경 변수 지정이 명령보다 먼저 적용되어야하므로 쉘에 의한 환경 변수 작성이 발생하지 않습니다. 만나다POSIX Shell Grammar Rules , 포인트 번호 7을 . 또한이를 통해 확인할 수 있습니다awk '{print ENVIRON["foo"]}' foo=bar /etc/passwd