root@ubuntu:~# echo ${x=1}
1
root@ubuntu:~# echo ${x:=1}
1
root@ubuntu:~# echo ${x-1}
1
root@ubuntu:~#
쉘 스크립트에 변수를 설정하는 데 세 가지 구문이 있는 이유는 무엇입니까?
세 가지 구문을 사용하면 어떤 기술적 이점이 있나요?
프로그래밍 언어에도 둘 이상의 언어가 없습니다.
답변1
그들은 약간 다른 일을 합니다. 실제로 마지막 항목은 echo ${x-1}
실제로 설정되지 않았습니다.엑스그러나 표현식의 값은 1인 경우에만 대체됩니다.엑스설정되지 않았습니다.
x=1
반면에 설정엑스무조건.
:= 연산자의 경우. 이것은에서 온 것입니다케시수동:
${parameter:=word}
If parameter is not set or is null then set it to word; the
value of the parameter is then substituted. Positional parameters may
not be assigned to in this way.
Ruby에서는 ||=
.
이 가족을 보면엑스더 많은 = 연산자가 있는데, :-
이것이 제가 본 것 중 가장 인기 있는 것입니다. 저것대안변수가 아직 설정되지 않은 경우 기본값으로 설정합니다. 따라서 다음과 같이 사용할 수 있습니다.
x=${1:-10}
영어는 다음과 같습니다. $1을 설정하지 않으면 10이 할당됩니다.엑스, 그렇지 않으면 다음에 할당됨엑스$1 가치. 함수에서는 매개변수에 기본값을 할당하는 효과가 있습니다. 그래서
f() {
typeset x
x=${1-10}
...
}
Python과 동일:
def f(x=10):
내 생각에 David Korn은 통신업체의 다양성이 다소 컸을 수도 있다는 점을 인정할 것입니다.POSIX 표준, 섹션 2.6.2그래서 아마도 거기에 머물 것입니다.
프로그래밍 언어에도 둘 이상의 언어가 없습니다.
위에서 언급했듯이 이것이 오해가 있습니다.정확히같은. 프로그래밍 언어에서는 할당문의 변형이 드물지 않습니다. 나는 ||=
그것을 Ruby에서 언급했습니다. 많은 언어에 이 기능 이 있습니다 +=
. -=
Perl에서 $x를 실행하기 전에 정의하지 않으면 1로 $x += 1
설정됩니다 $x
(그리고 "엄격한" 검사를 활성화하지 않으면 정말 안타까운 일입니다).
답변2
나는 "변수 할당을 위한 쉘 구문이 왜 그렇게 많은가?"라는 질문에 대한 유일한 대답이라고 생각합니다. "그들은 모두 약간씩 다르게 행동하기 때문입니다."
쉘 프로그래밍 언어에서는 $x
다음 중 하나를 수행합니다 ${x}
.다음으로 확장명명된 쉘 변수의 값입니다 x
. 즉, 쉘이 포함된 line을 해석할 때 변수 값으로 $x
대체됩니다 .$x
$ x=me; filepath=/home/$x
$ echo $filepath
/home/me
또한 셸은 부작용이 있는 확장을 포함하여 다양한 조건부 확장을 구현합니다.
조건부 직업
교체하기 전에 조건부로 할당:
${x=1}
x
이전에 설정하지 않은 경우 1로 설정합니다.${x:=1}
x
이전에 설정되지 않은 경우 1로 설정하거나 빈 문자열로 설정합니다.
예:
$ unset x
$ echo Hello, "${x=world}"
Hello, world
$ echo "$x"
world
$ # This sets x to the empty string
$ x=
$ echo Hello, "${x=world}"
Hello,
$ echo "$x"
$ echo Hello, "${x:=world}"
Hello, world
$ echo "$x"
world
조건부 확장
확장은 변수 또는 일부 고정 문자열의 값입니다. 변수는아니요변경되었습니다.
${x-1}
설정된${x}
경우 로 확장합니다 .x
그렇지 않으면 으로 확장합니다1
.${x:-1}
${x}
설정되어 있고 비어 있지 않은 경우x
다음으로 확장됩니다. 그렇지 않으면 으로 확장합니다1
.${x+1}
설정된1
경우 로 확장합니다 .x
그렇지 않으면 빈 문자열로 확장됩니다.${x:+1}
1
설정되어 있고 비어 있지 않은 경우x
다음으로 확장됩니다. 그렇지 않으면 빈 문자열로 확장됩니다.
예:
$ unset x
$ echo Hello, "${x-world}"
Hello, world
$ echo "$x"
$ # This sets x to the empty string
$ x=
$ echo Hello, "${x-world}"
Hello,
$ echo Hello, "${x:-world}"
Hello, world
$ echo "$x"
조건 오류
${x?error message}
x
설정하지 않으면 실패하고 오류 메시지가 인쇄됩니다.${x:?error message}
x
설정하지 않거나 빈 문자열로 설정하면 실패하고 오류 메시지가 인쇄됩니다.
실패하면 확장이 발생한 명령이 실행되지 않습니다. 쉘이 대화형이 아니면 쉘 자체가 종료됩니다.
콜론
:모든 조건부 구문에서 a를 사용 하면 설정되지 않은 변수가 빈 문자열로 설정된 변수와 동일한 방식으로 동작한다는 것을 알 수 있습니다 . 때로는 변수를 설정 해제하는 것이 쉽지 않기 때문에 이는 일반적으로 좋은 생각입니다. 예를 들어 위에 표시된 로컬 할당 구문에서 빈 문자열에 하위 변수를 할당하는 것은 쉽지만 하위 환경에서 변수를 제거하는 것은 쉽지 않습니다.
$ export foo=Goodbye
$ foo= dash -c 'echo "${foo-Hello}", world'
, world
$ foo= dash -c 'echo "${foo:-Hello}", world'
Hello, world
$ echo "$foo"
Goodbye
명령으로 조건부 확장
때로는 명령에서 실제로 사용하는 대신 조건부 확장을 수행하여 부작용을 제거하는 것이 편리할 때도 있습니다. 기술적으로 이는 불가능하지만 아무 작업도 수행하지 않는 특수 내장 명령을 사용할 수 있습니다 :
.
# Equivalent to:
# if [ -z "$x" ]; then x="default value"; fi
: "${x:=default value}"
# Equivalent to:
# if [ $# -lt 3 ]; then
# echo "Three arguments are required" 1>&2
# exit 1
# fi
: "${3?Three arguments are required.}"
변수 할당
셸은 스칼라 변수에 값을 할당하기 위한 간단한 구문을 제공합니다.
var=value
명령에 할당만 포함된 경우 할당은 쉘 환경의 일부가 됩니다. 그러나 할당이 유틸리티/스크립트 이름 앞에 있는 명령줄의 일부인 경우 할당은 다음에 적용됩니다.어린이하위 프로세스가 사용하는 환경은 다음과 같습니다.
$ foo=Hello; echo "$foo, world"
Hello, world
$ echo "$foo"
Hello
$ unset foo
$ foo=Hello echo "$foo, world"
, world
$ echo "$foo"
foo=Hello echo "$foo, world", the assignment is performed in the environment passed to
echo . However, the argument
"$foo, world" is evaluated in the main shell environment, in which
$foo has no value. Furthermore, when the child process (
echo , in this case) terminates, its environment is lost, so the assignment was useless. Contrast that with the case where the child process actually uses the variable: (
dash bash` 명령 is a Posix-compatible shell; I'm just using it here for clarity.
에서도 동일한 방식으로 작동합니다 . )
$ unset foo
$ foo=Hello dash -c 'echo "$foo, world"'
Hello, world
$ echo "$foo"
확장 할당 구문
일부 셸(예: bash, ksh 및 zsh)도 구문을 제공합니다.
var+=value
이로 인해 value
변수가 증가합니다. "추가"의 의미는 변수 유형에 따라 다릅니다 var
. 일반 문자열 변수의 경우 value
끝에 추가되고 var
, 정수로 선언된 변수의 경우 value
수학적으로 추가됩니다. ksh, zsh 및 일부 bash 버전에서는 이 할당 구문을 명령의 일부로 하위 할당에 사용할 수 있습니다. 변수를 숫자로 선언하는 방법에 대한 자세한 내용은 개별 셸 설명서를 참조하세요. (이것은아니요단순히 변수에 숫자를 할당하는 것만으로도 충분합니다. )
이러한 셸에는 다음 구문을 사용하여 할당되고 추가되는 배열 변수도 있습니다.
array=(value1 value2 ...)
array+=(value3 ...)
위 할당의 괄호는 문법적입니다. 왼쪽 괄호를 할당 마크업의 일부로 생각할 수 있습니다. 배열을 하위 환경으로 내보낼 수 없기 때문에 배열 할당은 간단한 명령의 일부로 사용할 수 없습니다.
일부 쉘에는 인덱스 할당을 지원하는 연관 배열이 있습니다. 선언 방법을 포함하여 연관 배열에 대한 자세한 내용은 개별 셸 설명서를 참조하세요.
산술 평가 과제
=
산술 평가에서는 C와 유사한 할당 연산자( , 등) 를 사용할 수 있지만 *=
이는 산술 할당만 수행합니다. +=
Posix 셸에는 산술 확장 구문 $((...))
과 for ((expr; expr; expr))
복합 명령문이라는 두 가지 산술 평가 컨텍스트만 있습니다. ( :
위의 특수 내장 함수를 사용하여 산술 확장을 명령문으로 변환할 수 있습니다.)
그러나 대부분의 쉘은 조건문을 허용하고 ((...))
배열 첨자 및 정수로 선언된 변수에 대한 할당과 같이 숫자가 필요한 컨텍스트에서 산술 평가도 사용합니다. 세부 사항은 쉘 매뉴얼을 참조하십시오.
변수 확장이 단지 정수가 아닌 산술 표현식으로 재해석되는 산술 평가 컨텍스트에는 주의가 필요합니다. 일부 쉘(예: bash)에서는 주입 공격을 통해 이를 악용할 수 있습니다. 가장 좋은 방법은 산술 평가 컨텍스트에서 신뢰할 수 없는 변수를 사용하지 않는 것입니다.