예
x=$y
그리고
x="$y"
그들은 항상 동등합니까? 이것을 찾는 방법을 잘 모르겠습니다. 지금까지 나는 x="$y"
"안전하게 플레이"하는 데 익숙했습니다. 그러나 나는 x=$1
분명히 여분의 큰따옴표가 필요하지 않다는 것을 사용하고 알아차렸습니다.
Open Group POSIX 문서에서 동작은 어디에 정의되어 있습니까?
답변1
예, POSIX 셸에서도 동일하다는 것이 보장됩니다 x=$y
. x="$y"
귀하 또는 다른 코드 독자가 큰따옴표가 어디에 있는지 확실하지 않은 경우~ 해야 하다사용됩니다(참조언제 큰따옴표가 필요합니까?), 큰따옴표를 포함하는 것이 혼란을 피하기 위해 더 안전한 선택일 수 있습니다.
POSIX 사양에서 (2.9.1절. “간단한 명령”):
주어진 간단한 명령을 실행해야 하는 경우 [...] 다음 확장, 할당 및 리디렉션이 명령 텍스트의 처음부터 끝까지 수행되어야 합니다.
- 다음 규칙에 따라 변수 할당 또는 리디렉션으로 식별되는 단어쉘 구문 규칙3단계와 4단계의 처리를 위해 저장합니다.
[...]
- 리디렉션은 다음에 설명된 대로 수행되어야 합니다.리디렉션.
- 물결표 확장, 매개변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 할당하기 전에 모든 변수 할당을 확장해야 합니다.
네 번째 항목에는 다음이 포함되지 않습니다.필드 분할또는경로명 확장("globbing"), 종종 단어가 나타날 때 발생하는 확장의 일부아니요변수 할당으로 인식됩니다. 할당 시 이러한 단계가 제거되므로 참조가 필요하지 않습니다.
당신은 또한 볼 수 있습니다섹션 2.6 “단어 확장”:
단어 확장 순서는 다음과 같습니다.
- 물결표 확장(참조물결표 확장), 매개변수 확장(참조매개변수 확장), 명령 대체(참조명령 대체) 및 산술 확장(참조산술 확장)은 처음부터 끝까지 실행되어야 합니다. 항목 5 참조토큰 인식.
- 필드 분할(참조필드 분할)은 null이 아닌 한 1단계에서 생성된 필드 부분에 대해 수행되어야 합니다
IFS
.- 경로명 확장(참조경로명 확장
set -f
)은 효력이 발생하지 않는 한 시행됩니다 .- 참조 제거(참조견적 삭제)은 항상 마지막에 실행되어야 합니다.
y
다음은 in x=$y
및 x="$y"
가 실제로 특수 인수 중 하나 인 경우에만 중요합니다 .*
@
"$@"
다음으로 확장되므로 참고하세요.목록문자열의 경우 what x=$@
및 x="$@"
do가 지정되지 않지만 x=$*
와 동일합니다 x="$*"
. 일부 쉘(예: bash
, ksh93
) 에서는 $@
의 첫 문자가 공백인 경우와 동일하게 사용되는 반면, 다른 쉘(예: busybox, , )에서는 설정 값의 첫 번째 문자를 사용하는 경우와 동일합니다.$*
$IFS
sh
dash
zsh
$*
$IFS
답변2
일반적으로 다음과 같은 것들이 있습니다.둘변수를 정의할 수 있는 섹션입니다.
선행 변수 할당
대시보드 매뉴얼에는 간단한 명령이 설명되어 있습니다.
"name=value" 형식의 선행 단어가 제거됩니다.
즉,
x=$y
정확히x="$y"
.즉,2.9.1절. “간단한 명령”토큰화나 경로 이름 확장은 적용되지 않습니다. 이 두 확장자는 새로운 단어를 생성할 수 있는 유일한 확장자이므로 IFS 문자가 포함된 변수를 분할하거나 여러 파일 이름을 일치시키는 것은 불가능합니다. 거기서 한 마디는
x=$y
한 마디로 남을 것이다.나머지 매개변수
"명령 이름"을 나타내는 단어가 발견되면 구문 분석 변경 및 할당이 분할되어 다른 것이 될 수 있습니다.
Bash 매뉴얼에서는 이를 다음과 같이 설명합니다.
할당문은 별칭, 선언, 조판, 내보내기, 읽기 전용 및 로컬 내장 명령(선언 명령)에 대한 인수로 나타날 수도 있습니다.
아직 인용해야 할 곳이 있습니다. 처럼
declare x="$y"
.물론 POSIX에서는
export
and 만readonly
의미가 있습니다.이제 yash에서만 실패합니다.
$ yash -c 'unset x; y="one two"; readonly x=$y; echo "x=$x"' x=one
그렇습니다. 일반적으로 x=$y
완전히 x="$y"
동일합니다 .와는 별개로어떤 경우에는 명령 이름 뒤에 변수 할당이 존재합니다.