![쉘 명령에 대한 gawk 변수 이스케이프](https://linux55.com/image/112240/%EC%89%98%20%EB%AA%85%EB%A0%B9%EC%97%90%20%EB%8C%80%ED%95%9C%20gawk%20%EB%B3%80%EC%88%98%20%EC%9D%B4%EC%8A%A4%EC%BC%80%EC%9D%B4%ED%94%84.png)
를 사용할 작은 gawk 스크립트를 실행하려고 합니다 system()
. 파일 목록을 가져와서 find
다음과 같이 스크립트를 실행하고 싶습니다.
find <arguments> -printf "%f\n" | script.awk
문제는 이러한 파일에 공백, 따옴표, 대괄호와 같은 특수 문자가 포함되어 있다는 것입니다. 예를 들어:
$ ls
'Aujourd'\''hui C'\''est Toi (Orchestral).flac'
나는 다음과 같은 다양한 참고 자료를 시도했습니다.
system("<command> \""$0"\"")
이:
system("<command> \'"$0"\'")
모든 종류의 오류가 발생합니다. 일부는 에서 sh -c
, 일부는 gawk
... 에서 발생합니다.
$0
이러한 모든 문제에 직면하지 않고 gawk 스크립트의 레코드나 기타 변수를 쉘 명령으로 전달할 수 있는 방법이 있습니까 ?
노트:일시적으로 파일 이름을 바꾸는 것이 더 쉬울 수도 있지만 이를 피하는 것이 더 어렵다는 것을 알았습니다.
편집하다:
제안된 답변 중 어느 것도 내 문제를 해결하지 못하므로 문제에 대한 보다 구체적인 설명은 다음과 같습니다. 다음을 사용하여 명령을 실행하려고 합니다.2이상한 변수. 예:
내가 실행하면 :
system("metaflac --show-tag=ARTIST \""FILE"\"")
인용했기 때문에 오류가 발생하지 않으며 FILE
큰따옴표가 포함되어 있지 않기 때문에 모든 것이 잘 작동합니다.
하지만 내가 실행하면 :
system("metaflac --set-tag=ARTIST="AWK_VAR_WITH_ARTIST_VALUE" "\"FILE\")
참조했는데도 metaflac
flac 파일을 찾을 수 없다고 에러가 뜹니다. 오류 메시지를 읽을 때 파일 이름이 별도의 단어로 구분되어 있는 것을 볼 수 있습니다.
답변1
system("<command> \"$0\"")
이것을 프로세스에 쓰는 awk의 기능으로 대체할 수 있습니다 print $0 | "pre;<command> \"$v\""
.앞으로부분은 stdin을 쉘 변수 v로 읽습니다. Bash에서는 다음과 같이 됩니다 read -r v
.
awk 'BEGIN{ cmd="read -r v; ls -ld \"$v\"" }
{ print $0 | cmd; close(cmd); }'
파일 이름의 개행과 같은 끔찍한 일을 처리하려면 find에서 print0 경로를 사용하거나 awk가 이를 허용하는 경우 RS='\0'
bash를 사용할 수 있습니다.
find . -print0 |
awk -v RS='\0' '
BEGIN{ cmd="read -r -d \"\" v; ls -ld \"$v\"" }
{ print $0 "\x00" | cmd; close(cmd); }'
답변2
공백과 작은따옴표의 특정 경우에는 문자열을 큰따옴표로 묶는 것만으로도 충분합니다.
$ find -name 'Aujour*' -printf "%f\n" | awk '{system("ls -l \""$0"\"")}'
-rw-rw-r-- 1 user user 0 May 26 11:27 Aujourd'hui C'est Toi (Orchestral).flac
find
또는 쉘이 쉘 인용 형식 지정자를 제공하는 경우 내부 대신 이를 사용하는 것을 고려할 수 있습니다 -printf
.
$ find -name 'Aujour*' -exec printf '%q\n' {} \; | awk '{system("ls -l "$0)}'
-rw-rw-r-- 1 user user 0 May 26 11:27 ./Aujourd'hui C'est Toi (Orchestral).flac
help printf
예를 들면 다음과 같습니다 bash
.
%q quote the argument in a way that can be reused as shell input