쉘 스크립트에 변수를 설정하는 데 세 가지 구문이 있는 이유는 무엇입니까?

쉘 스크립트에 변수를 설정하는 데 세 가지 구문이 있는 이유는 무엇입니까?
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 toecho . 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)에서는 주입 공격을 통해 이를 악용할 수 있습니다. 가장 좋은 방법은 산술 평가 컨텍스트에서 신뢰할 수 없는 변수를 사용하지 않는 것입니다.

관련 정보