$ (command $ arg)를 인용하는 올바른 방법은 무엇입니까?


17

몇 년 동안 저를 괴롭혔던이 수수께끼를 풀어야 할 때가되었습니다 ...

나는 때때로 이것을 만나고 이것이 갈 길이라고 생각했다.

$(comm "$(arg)")

그리고 내 견해는 경험에 의해 강력하게 뒷받침된다고 생각했습니다. 그러나 나는 더 이상 확신하지 못한다. Shellcheck 도 마음을 사로 잡을 수 없습니다. 둘 다입니다.

"$(dirname $0)"/stop.bash
           ^-- SC2086: Double quote to prevent globbing and word splitting.

과:

$(dirname "$0")/stop.bash
^-- SC2046: Quote this to prevent word splitting.

뒤에 논리는 무엇입니까?

(이것은 Shellcheck 버전 0.4.4, btw입니다.)


1
모든 대체물을 인용하십시오.
Ignacio Vazquez-Abrams

3
이것처럼 : "$(dirname "$0")"/stop.bash? 작동하는 것 같습니다 ... 이야기는 무엇입니까?
Tomasz

1
bash는 상황이 언제 바뀌 었는지 알기에 충분히 영리합니다.
이그나시오 바스케스-아 브람스

1
다음과 같이 생각하십시오 : shell_level_1 $(shell_level_2) shell_level_1: 당신이 안에있을 때 $(....)쉘의 "하위 레벨"을 입력하십시오. 그러나 기본 레벨에있는 것처럼 작성할 수 있습니다 (즉, "대신 대신 직접 쓸 수 있음 \"). 예 : touch "/tmp/a file" ; echo "its size is: $(find "/tmp/a file" -ls | awk '{print $5}) ..." : if you used backticks you'd have to \ "/ tmp / a file \"`및을 찾으십시오 print \$5. 와 $(...)필요가 없습니다 : 쉘 새로운 수준에 적응하고 통역 지금 너무 그 수준에 인 것처럼 직접 쓸 수 있습니다.
Olivier Dulac

"Shellcheck도 마음을 구성 할 수 없습니다." -두 번의 달리기는 서로 다른 두 개의 메시지를 가지며 다른 위치를 가리 킵니다. 둘 다 원해
이즈 카타

답변:


45

를 사용해야 "$(somecmd "$file")"합니다.

따옴표가 없으면 공백이있는 경로가에 인수로 분할되어 somecmd잘못된 파일을 대상으로합니다. 내부에 따옴표가 필요합니다.

출력 결과에 공백이 somecmd있으면 분할이 발생하므로 전체 명령 대체 외부에 따옴표가 필요합니다.

명령 대체 내부의 따옴표는 외부의 따옴표에 영향을 미치지 않습니다. Bash의 자체 참조 매뉴얼은 이것에 대해 명확하지 않지만 BashGuide는 명시 적으로 언급합니다 . POSIX텍스트 에도 "유효한 쉘 스크립트" 가 허용 되므로 다음과 같은 내용이 필요합니다 $(...).

$(command)형식을 사용하면 여는 괄호 다음에 일치하는 닫는 괄호 뒤에있는 모든 문자가 명령을 구성합니다. 지정되지 않은 결과를 생성하는 리디렉션만으로 구성된 스크립트를 제외하고 모든 유효한 쉘 스크립트를 명령에 사용할 수 있습니다.


예:

$ file="./space here/foo"

ㅏ. 따옴표, dirname모두 처리되지 ./spacehere/foo:

$ printf "<%s>\n" $(dirname $file)
<.>
<here>

비. inside, dirnameprocesses ./space here/foo, giving ./space here을 두 개로 나눕니다.

$ printf "<%s>\n" $(dirname "$file")
<./space>
<here>

씨. 외부를 인용 하고 ,와를 dirname모두 처리 하여 별도의 줄로 출력하지만 이제 두 줄은 단일 인수를 형성합니다 ../spacehere/foo

$ printf "<%s>\n" "$(dirname $file)"
<.
here>

디. 내부와 외부를 인용하면 정답이됩니다.

$ printf "<%s>\n" "$(dirname "$file")"
<./space here>

( dirname첫 번째 인수 만 처리하면 더 간단했을 수 있지만 사례 a와 c의 차이는 표시되지 않습니다.)

함께합니다 dirname(다른 가능성이) 당신은 또한 추가 할 필요가 --,이 대시로 시작하는 일 경우 옵션으로 촬영 사용 그렇게되는 파일 이름을 방지하기 위해 "$(dirname -- "$file")".


16
참고 : 일반적으로 따옴표는 bash에 중첩되지 않습니다. 그러나이 경우, $( )새로운 컨텍스트를 생성하므로, 그 안의 따옴표는 그 외부의 따옴표와 무관합니다. 그리고 당신은 일반적으로 두 문맥에서 따옴표를 원합니다.
Gordon Davisson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.