내가 달릴 때, Ashes, Sprints 및 Slams에서
$ echo ab$
그것은 돌아온다
ab$
이 동작은 POSIX에 의해 지정됩니까, 아니면 POSIX 호환 셸 간의 일반적인 규칙입니까? POSIX Shell Command Language 페이지에서 이 동작에 대한 언급을 찾을 수 없습니다.
답변1
$
그 자체로는 특별한 의미가 없습니다(try ). (또는 ) ,, echo $
와 같은 다른 후속 문자와 결합하여 확장자를 형성할 때만 특별한 의미가 있습니다 .$var
${var}
$(util)
$((1+2))
"특별한" 의미 $
는 확장이 POSIX 표준에 정의되어 있다는 것입니다.토큰 인식:
현재 문자가 따옴표가 없는
$
or 인 경우`
쉘은 따옴표가 없는 소개 문자 시퀀스$
인 or${
,$(
또는`
, 및 에서 매개변수 확장, 명령 대체 또는 산술 확장에 대한 후보의 시작을 식별해야 합니다$((
. 쉘은 확장할 장치의 끝을 결정하기에 충분한 입력을 읽어야 합니다(인용된 장에서 설명했듯이). 문자를 처리할 때 중첩된 확장 또는 인용 인스턴스가 대체에서 발견되면 쉘은 발견된 구성에 대해 지정된 대로 이를 반복적으로 처리해야 합니다. 대체 시작부터 끝까지 발견된 문자(내장된 구조를 식별하는 데 필요한 재귀를 허용)는 포함되거나 포함된 대체 연산자 또는 따옴표를 포함하여 수정되지 않은 결과 마크업에 포함되어야 합니다. 토큰은 대체가 끝날 때까지 구분되어서는 안 됩니다.
따라서 $
확장이 형성되지 않으면 다른 구문 분석 규칙이 적용됩니다.
이전 문자가 단어의 일부인 경우 현재 문자가 해당 단어에 추가되어야 합니다.
그것은 당신의 ab$
끈을 덮습니다.
별도의 경우 $
("새 단어" $
자체는 다음과 같습니다):
현재 문자가 새 단어의 시작 부분으로 사용됩니다.
이것중요성$
비표준 확장을 포함하는 생성된 단어는 POSIX에서 명시적으로 지정되지 않음으로 정의됩니다.
또한 $
의 마지막 문자는 이지만 $$
이는 현재 쉘의 PID를 보유하는 변수이기도 합니다. 에서는 bash
히스토리 !$
확장을 호출할 수 있습니다(이전 명령의 마지막 인수). 따라서 일반적으로 아니요, $
인용되지 않은 단어의 끝은 의미가 없지만 단어의 끝은 적어도 표준 확장을 의미하지 않습니다.
답변2
상황에 따라 이는 명시적으로 지정되지 않거나(구현이 원하는 대로 수행될 수 있음) 관찰한 방식으로 발생해야 합니다. 특정 시나리오 echo ab$
에서는POSIX는 관찰한 "ab$"의 출력을 강제합니다.그리고이는 지정되지 않았습니다.. 마지막으로 다양한 사례에 대한 간략한 요약입니다.
두 가지 요소가 있습니다. 먼저 단어로 레이블을 지정하고 해당 단어를 해석하는 것입니다.
토큰화
POSIX 토큰화 요구 사항A는 $
유효한 시작이 아닙니다.매개변수 확장,명령 대체, 또는산술 대체WORD
생성되는 토큰의 문자 그대로의 일부로 처리됩니다 . 이는 규칙 5 때문입니다("현재 문자가 따옴표가 없는 $
or 이면 `
쉘은 따옴표가 없는 소개 문자 시퀀스에서 매개변수 확장, 명령 대체 또는 산술 확장에 대한 후보의 시작을 식별해야 합니다: $
또는 ${
, 각각 $(
또는 `
, $((
" ) 여기서는 이러한 확장이 불가능하므로 적용하지 마세요. 매개변수 확장에는 유효한 이름이 있어야 하며, 빈 이름은 유효하지 않습니다.
이 규칙은 적용되지 않으므로 적용되는 규칙을 찾을 때까지 계속해서 이를 따를 것입니다. 두 가지 후보는 #8("이전 문자가 단어의 일부인 경우 현재 문자가 해당 단어에 추가되어야 합니다.")과 #10("현재 문자가 새 단어의 시작으로 사용됩니다.")입니다. 각각 echo a$
및 에 적용됩니다 echo $
.
세 번째 형태도 특별한 매개변수의 이름이 아니기 echo a$+b
때문에 같은 상황에 속한다 . +
규칙의 다른 부분을 트리거하므로 이에 대해 나중에 다시 설명하겠습니다.
따라서 사양에서는 $
문법적으로 단어의 일부로 처리되어 나중에 추가로 처리될 수 있도록 요구합니다.
단어 확장
이런 식으로 입력을 구문 분석하고 $
이를 단어로 포함시킨 후,단어 확장읽은 모든 단어에 적용됩니다. 모든 단어가 처리됩니다.개별적으로.
따옴표가 없는 "$" 뒤에 다음 문자 중 하나 이외의 문자가 오는 경우:
- 숫자
- 특수 매개변수 중 하나의 이름(참조:특수 매개변수)
- 변수 이름의 유효한 첫 번째 문자
- ㅏ
<left-curly-bracket>
('{')- ㅏ
<left-parenthesis>
결과가 지정되지 않았습니다.
여기서 "지정되지 않음"은 특별한 용어입니다.
- 이 경우 일관된 쉘은 모든 동작을 선택할 수 있습니다.
- 자격을 갖춘애플리케이션특정 행동에 의존할 수 없음
귀하의 예 echo ab$
에서는$
뒤처지지 않음어느특징이므로 규칙이 적용되지 않으며 지정되지 않은 결과가 호출되지 않습니다. 전혀 확장이 발생하지 않았 $
으므로 존재하고 인쇄됩니다.
어디회의위의 세 번째 경우에 적용되는 것은 다음과 같습니다 echo a$+b
. 뒤에 , 숫자 $
가 +
아님, 특수 매개변수( @
, *
, #
, ?
, -
, $
또는 !
) 0
, 변수의 시작이름(밑줄 또는 문자휴대용 문자 세트) 또는 대괄호 중 하나입니다. 이 경우 동작은 지정되지 않습니다. 일관된 쉘+
확장이라는 특별한 매개변수를 고안하는 것이 허용되었습니다.및 적격 신청서쉘이 그렇지 않다고 가정해서는 안됩니다.. 쉘은 오류 보고를 포함하여 원하는 모든 작업을 수행할 수도 있습니다.
예를 들어 POSIX 모드를 포함한 zsh는" 변수의 집합" $+b
으로 해석됩니다 .b
그리고 그 자리를 1이나 0으로 바꿉니다. 또한 ~
및 에 대한 확장도 있습니다 =
. 이는 규정을 준수하는 동작입니다.
이런 일이 일어날 수 있는 또 다른 곳은 입니다 echo "a$ b"
. 다시 말하지만, 쉘은 원하는 것을 수행할 수 있으며 스크립트 작성자로서 $
리터럴 출력을 원한다면 이스케이프해야 합니다. 그렇지 않으면 효과가 있을 수 있지만 의존할 수는 없습니다. 이는 사양의 절대적인 문자이지만 이러한 세분성은 의도적이거나 고려된 것이 아니라고 생각합니다.
요컨대
echo ab$
:텍스트 출력, 완전히 지정됨echo a$ b
:텍스트 출력, 완전히 지정됨echo a$ b$
:텍스트 출력, 완전히 지정됨echo a$b
: 매개변수 확장b
, 완전히 지정됨echo a$-b
:특수 매개변수 확장-
, 완전히 지정됨echo a$+b
: 지정되지 않은 동작echo "a$ b"
: 지정되지 않은 동작
$
단어 끝의 a 에 대한 해당 동작을 신뢰할 수 있으며 문자 그대로 처리하고 echo
인수의 일부로 명령에 전달해야 합니다. 이는 셸에 대한 일관성 요구 사항입니다.