쉘 명령에 대한 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

관련 정보