내가 찾을 수 있는 유일한 참고자료이것은 사양입니다:
"$()"에 대한 명령문과 유사하게 "동봉된 "${"에서 일치하는 "}"까지의 문자는 큰따옴표의 영향을 받지 않아야 합니다."와 같은 명령문을 포함하는 것이 좋습니다. 그러나 System V 셸의 역사적 관행으로 인해 이를 방지할 수 있습니다.
분명한 질문은 "그 역사적 질문은 무엇이었는가"이며, 더 중요한 것은 그것이 오늘날 우리에게 어떤 영향을 미치는가입니다.
C.2.5 Parameters and Variables
이 페이지 제목 아래에는 인용 확장의 예가 많이 있으며, 모두 나열하기 위해 최선을 다한 것 같지만 큰따옴표가 두 번 나타나는 예는 없습니다 .
설명하다
문제는 다음 6가지 인용 대안의 결과와 관련이 있습니다.
$b
,"$b"
,${a-$b}
,${a-"$b"}
"${a-$b}"
그리고"${a-"$b"}"
처음 5개는 POSIX에 의해 정의되며 일부 쉘은 이러한 확장의 결과에 동의합니다. 일부 값은 다음 값을 기준으로 분할됩니다 $IFS
.
$ export a=abc; for sh in dash ksh93 bash; do $sh -c 'IFS="bl"; b=value
printf "<%s> " 1$b 2"$b" 3${a-$b} 4${a-"$b"} 5"${a-$b}" 6"${a-"$b"}";
echo'; done
<1va> <ue> <2value> <3a> <c> <4a> <c> <5abc> <6abc>
<1va> <ue> <2value> <3a> <c> <4a> <c> <5abc> <6abc>
<1va> <ue> <2value> <3a> <c> <4a> <c> <5abc> <6abc>
하지만 "${1-"$var"}"
사양 어딘가에 정의되어 있습니까?
즉,반복하다큰따옴표(외부 및 내부)
추가 1
관련 정보로 다음 결과를 살펴보십시오. 이전 코드와 다음 코드의 유일한 차이점은 $a
설정되지 않았다는 것입니다.
$ unset a; for sh in dash ksh93 bash; do $sh -c 'IFS="bl"; b=value
printf "<%s> " 1$b 2"$b" 3${a-$b} 4${a-"$b"} 5"${a-$b}" 6"${a-"$b"}";
echo'; done
<1va> <ue> <2value> <3va> <ue> <4value> <5value> <6value>
<1va> <ue> <2value> <3va> <ue> <4value> <5value> <6va> <ue>
<1va> <ue> <2value> <3va> <ue> <4value> <5value> <6value>
추가 2
실제로 모든 인용 옵션을 테스트할 때 일반 쉘은 충돌하는 방식으로 작동합니다.
$ for sh in dash ksh93 bash; do $sh -c 'IFS="bl"; b=value
printf "<%s> " 1\n 2"\n" 3${a-\n} 4${a-"\n"} 5"${a-\n}" 6"${a-"\n"}";
echo'; done
<1n> <2\n> <3n> <4\n> <5\n> <6\n>
<1n> <2\n> <3n> <4\n> <5\n> <6n>
<1n> <2\n> <3n> <4\n> <5\n> <6n>
여기에는 zsh도 포함되지 않습니다!.
답변1
POSIX에서는 왜
"${1-"$var"}"
언급되지 않습니까?
확장 프로그램 내부와 외부에 따옴표가 있다는 것이 무엇을 의미하는지 전혀 명확하지 않은 것 같고 정의되지 않도록 승인된 변경 사항이 있는 것 같습니다.
그러나 확장 외부에서 따옴표를 사용하는 것이 일반적입니다. 이는 단어(필드) 분할 및 와일드카드를 방지하기 위해 수행하는 작업입니다. 확장 기능에 넣는 것에 대한 언급도 있습니다.
부분2.2.3 큰따옴표설명하다
큰따옴표(
""
)로 묶인 문자는 다음과 같이 백틱, <달러 기호> 및 <백슬래시> 문자를 제외하고 큰따옴표 안의 모든 문자의 리터럴 값을 유지합니다.
${
[...] 일치하는 대괄호의 문자열에서}
,이스케이프 처리되지 않은 짝수 개의 큰따옴표또는 작은따옴표(있는 경우)가 있어야 합니다.
명령 대체의 경우 다음과 같습니다.
인용된 문자열의 입력 문자는 및 사이에도 포함되며
$(
일치 항목은)
큰따옴표로 묶어서는 안 됩니다. [...]
매개변수 확장에는 이에 대한 언급이 없으므로 내부 문자 ${...}
도 외부 따옴표의 영향을 받는다는 의미입니다.
${foo-\n}
vs.(사례 3과 5)의 예는 "${foo-\n}"
실제로 vs. \n
와 마찬가지로 외부 따옴표가 백슬래시를 보호한다는 것을 보여줍니다."\n"
하지만 내부 인용문과 외부 인용문을 모두 언급하지 않는 것 같고, 무엇을 해야 할지 명확하지 않습니다.
내부 문자가 외부 따옴표의 영향을 받는 경우 가능한 설명 중 하나는 첫 번째 내부 큰 따옴표입니다.마치다참조하면 두 번째는 이를 다시 시작한 다음 whatever
역참조합니다. Ksh는 다음과 같이 이 해석을 상당히 일관되게 따르는 것 같습니다.
$ printf "<%s>\n" "${foo-"foo \n *"}"
<foo>
<n>
<file1.txt>
<file2.txt>
이것이 매우 유용한지는 잘 모르겠고, 이 작업을 수행하는 다른 쉘도 거의 없습니다. (적어도 최근에 시도한 것들로 판단하면.)
<foo \n *>
다른 경우에는 문자열이 완전히 인용된 것처럼, 내부 큰따옴표가 단순히 문자를 인용해야 한다는 사실을 강조하는 것처럼 출력의 대부분이 단지 입니다 .
그런 다음 Bash와 Dash는 백슬래시를 일관되지 않은 방식으로 처리하는 것 같고 인쇄는 <foo n *>
내가 생각할 수 있는 논리적 규칙을 따르지 않는 것 같습니다. \n
마치 인용되지 않은 것처럼 동작하는 반면 *
및 공백은 마치 인용된 것처럼 동작합니다.
넣으면 더 털이 날 것 같아요하나의인용 부호.
이러한 불일치를 목격하면서 이 문제가 이전에 논의된 것은 아마도 놀라운 일이 아닐 것입니다.이를 명시적으로 정의되지 않게 만드는 보류 중인 변경 사항이 있는 것 같습니다., 관련 부분은 다음과 같습니다.
하위 문자열 처리를 제공하는 네 가지 유형 이외의 매개변수 확장의 경우 확장이 발생하는 큰따옴표는 둘러싸는 "${"에서 일치하는 "}"까지 문자열의 모든 문자의 리터럴 값을 유지해야 합니다. 큰따옴표, 역따옴표 및. 문자열에 이스케이프 처리되지 않은 큰따옴표 문자가 있으면 동작이 지정되지 않습니다(내장된 명령 대체 제외).
그리고
셸 구현은 "${...}" 내에서 이스케이프 처리되지 않은 큰따옴표 문자를 처리하는 방법에 따라 매우 다양합니다(4개의 하위 문자열 처리 변형 제외). 따라서 표준은 동작을 지정하지 않습니다. [...] "${...}" 형식 처리의 차이로 인해 System V 쉘, BSD 및 KornShell 간의 역사적 불일치가 발생했습니다. POSIX.1-2008의 쉘 및 유틸리티 볼륨에 있는 텍스트는 다음과 같습니다. 너무 많은 응용 프로그램을 중단하지 않고 혼합을 시도하십시오.
이것이 역사적인 이유인 것 같습니다.
첫 번째 내용을 읽는 방식은 ${foo-"bar"}
단지 가 아니라 또한 의미하는 것 같습니다 "${foo-"bar"}"
. 전자는 쉘 간에 다른 결과를 제공하는 경향이 덜한 것 같습니다.
2010년에는 이에 대한 논의를 찾지 못했지만, 작은 따옴표의 작동 방식을 다루는 2016년의 메시지는 다음과 같습니다.
인용된 ${ }는 쉘의 [가장 털이 많은] 부분 중 하나이며 어떤 의미에서 가장 무섭고 재현하기가 정말 어렵습니다. 이 모든 것이 지정되지 않았거나 문제가 될 것이라는 것은 놀라운 일이 아닙니다 8(아직 이해할 수 없음).
좋아요 Geoff의 입장은 Issue 7 텍스트가 셸이 아닌 애플리케이션에 대한 요구 사항이며, 더 나아가 작은 따옴표와 큰 따옴표 각각의 의도에 대해 요구 사항이 모호하게 표현되어 있다는 것입니다(즉, 중첩될 수 없음).
따라서 해석 221을 논의할 때 정확하다고 지적할 수 있는 쉘 동작은 없으며 논의의 일부에는 무엇이 올바른지 결정하고 이를 명확하게 표현하는 것이 포함됩니다.