쉘 명령에 대한 gawk 변수 이스케이프

쉘 명령에 대한 gawk 변수 이스케이프

를 사용할 작은 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\")

참조했는데도 metaflacflac 파일을 찾을 수 없다고 에러가 뜹니다. 오류 메시지를 읽을 때 파일 이름이 별도의 단어로 구분되어 있는 것을 볼 수 있습니다.

답변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

관련 정보