애쉬, 대시, 배쉬에서 내가 달릴 때
$ echo ab$
그것은 반환
ab$
이 동작이 POSIX에 의해 지정 되었습니까 아니면 POSIX 호환 쉘에서 일반적인 규칙입니까? POSIX Shell Command Language 페이지에서이 동작을 언급 한 내용을 찾을 수 없습니다.
답변
$
그 자체로 특별한 의미를 갖지 않으며 (try echo $
), 그 후에 다른 캐릭터와 결합하여 확장을 형성 할 때만 $var
( 예 : (또는 ${var}
), $(util)
) $((1+2))
.
이 $
섹션에서 POSIX 표준의 확장 정의로 의미의 “특별한”를 얻는다 토큰 인식을 :
현재 문자가 인용 부호가
$
없거나 또는 인`
경우, 쉘은 각각 인용 부호가없는 문자 순서 ($
또는${
,$(
또는`
, 및) 로부터 매개 변수 확장, 명령 대체 또는 산술 확장 후보의 시작을 식별해야한다$((
. 쉘은 확장 될 장치의 끝을 결정하기에 충분한 입력 값을 읽어야 합니다 (인용 된 섹션에 설명 된대로)). 문자를 처리하는 동안 확장 또는 인용의 인스턴스가 대체 내에 중첩 된 것으로 발견되면 쉘은 발견 된 구문에 대해 지정된 방식으로 재귀 적으로 처리해야합니다. 포함 된 구성을 인식하는 데 필요한 재귀를 허용하는 대체의 시작부터 끝까지 발견 된 문자는 포함되거나 포함 된 대체 연산자 나 따옴표를 포함하여 결과 토큰에 수정되지 않은 상태로 포함되어야합니다. 토큰은 교체가 끝날 때까지 구분되지 않습니다.
따라서 $
확장을 구성하지 않으면 다른 구문 분석 규칙이 적용됩니다.
이전 문자가 단어의 일부인 경우 현재 문자가 해당 단어에 추가됩니다.
그것은 당신의 ab$
문자열을 다룹니다 .
고독한 경우 $
(“새로운 단어”는 $
그 자체 일 것임 ) :
현재 문자는 새로운 단어의 시작으로 사용됩니다.
표준 확장이 아닌를 포함하는 생성 된 단어 의 의미 는 $
POSIX에서 지정하지 않은 것으로 명시 적으로 정의됩니다.
또한 $
의 마지막 문자 $$
이지만 현재 쉘의 PID를 보유하는 변수이기도합니다. 에서은 bash
, !$
역사 확장 (이전 명령 AF 마지막 인자)를 호출 할 수 있습니다. 따라서 일반적으로 $
인용되지 않은 단어의 끝에서 의미가없는 것은 아니지만 단어의 끝에서 최소한 표준 확장을 나타내는 것은 아닙니다.
답변
정확한 상황에 따라, 이것은 명시 적으로 지정되지 않았거나 (구현대로 구현할 수 있음) 관찰 한대로 발생해야합니다. 정확한 시나리오에서 echo ab$
, POSIX는 관찰 된 것을 “AB $”출력을 의무화 하고 는 지정되지 않습니다 . 모든 다른 경우에 대한 간단한 요약이 끝났습니다.
먼저 단어로 토큰 화 한 다음 해당 단어를 해석하는 두 가지 요소가 있습니다.
토큰 화
POSIX의 tokenisation는 필요$
유효한 개시 아니라고 파라미터 확장 , 명령 치환 또는 산술 교체 의 리터럴 부분 간주 WORD
구성된 토큰된다. 규칙 5 ( “현재의 문자는 인용 부호가없는 경우 때문입니다 $
나 `
: 쉘이 자신의 소개 인용 부호로 둘러싸이지 않은 캐릭터 시퀀스에서 매개 변수 확장, 명령 치환, 또는 산술 확장에 대한 후보자의 시작을 식별해야한다 $
나 ${
, $(
나 `
, 그리고 $((
각각” )는 해당 확장이 실행 가능하지 않으므로 적용되지 않습니다. 매개 변수 확장에 유효한 이름이 나타나야하며 빈 이름이 유효하지 않습니다.
이 규칙은 적용되지 않았으므로 해당 규칙을 찾을 때까지 계속 따릅니다. 두 후보는 # 8 ( “이전 문자가 단어의 일부인 경우 현재 문자가 해당 단어에 추가됩니다.”) 및 # 10 ( “현재 문자는 새 단어의 시작으로 사용됩니다.”)입니다. echo a$
및 echo $
각각에 적용됩니다 .
특별한 매개 변수의 이름이 아니기 echo a$+b
때문에 동일한 균열을 겪는 형태의 세 번째 경우도 있습니다 +
. 이것은 규칙의 다른 부분을 트리거하기 때문에 나중에 다시 돌아올 것입니다.
따라서, 명세서 $
는 구문 적으로 단어의 일부로 간주 되어야하고, 이후에 추가로 처리 될 수 있어야한다.
단어 확장
이 방법으로 입력을 구문 분석 한 후 $
단어에 단어를 포함 시키면 읽은 각 단어에 단어 확장 이 적용됩니다. 각 단어는 개별적 으로 처리 됩니다 .
따옴표없는 ‘$’뒤에 다음 중 하나가 아닌 문자가 오는 경우 :
- 숫자
- 특별한 매개 변수 중 하나의 이름은 (참조 특수 매개 변수 )
- 변수 이름의 유효한 첫 문자
- A
<left-curly-bracket>
( ‘{‘)- ㅏ
<left-parenthesis>
결과는 지정되어 있지 않습니다.
“지정되지 않음”은 여기서 특별한 용어입니다.
- 이 경우 적합한 쉘은 모든 동작을 선택할 수 있습니다
- 적합한 응용 프로그램 은 특정 동작에 의존 할 수 없습니다
당신의 예에서, echo ab$
의는 $
다음되지 않은 모든 문자를 이 규칙이 적용되지 않도록하고, 지정되지 않은 결과가 호출되지 않습니다. 에 의해 촉발 된 확장은 없으므로 $
문자 그대로 존재하고 인쇄됩니다.
어디는 것입니다 적용 위에서 세 번째 경우이다 echo a$+b
. 여기 $
뒤에 +
숫자, 특수 파라미터하지 않다 ( @
, *
, #
, ?
, -
, $
, !
, 또는 0
) 변수의 시작의 이름 (또는 언더에서 영 휴대용 문자 집합 ), 또는 하나의 브래킷. 이 경우 동작은 지정되지 않습니다. 적합한 쉘 은 +
expand 라는 특수 매개 변수를 발명 할 수 있으며, 적합한 응용 프로그램 은 쉘이 그렇지 않다고 가정해서는 안됩니다 . 쉘은 오류보고를 포함하여 원하는 다른 작업을 수행 할 수 있습니다.
예를 들어 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
인수의 일환으로 명령을 실행합니다. 이것이 쉘의 적합성 요구 사항입니다.