x=( $@ )와 x="$@" 할당의 차이점

x=( $@ )와 x="$@" 할당의 차이점
#!/bin/bash

if [ $# -gt 0 ]; then
    snum=( $@ ) 
    echo $snum
fi

./testscript.sh 1234 4568 The Output of echo command is only 와 같은 스크립트를 실행할 때 1234모든 위치 매개변수의 배열을 구축하지 않는 것 같나요?

#!/bin/bash

if [ $# -gt 0 ]; then
    snum="$@" 
    echo $snum
fi

./testscript.sh 1234 4568 출력을 실행하면 다음과 같습니다.1234 4568

snum=( $@ )왜 첫 번째 위치 매개변수만 사용되는지 궁금합니다 .

답변1

목록 컨텍스트 "$@"(큰따옴표 포함)에서 사용하여 가져옵니다.목록개별적으로 인용된 위치 매개변수입니다.

스칼라 컨텍스트 "$*"(큰따옴표 포함)에서 사용하여 위치 인수를 연결합니다.단일 문자열첫 번째 문자 $IFS(일반적으로 공백)를 구분 기호로 사용합니다.

$@따옴표 없이(첫 번째 예에서처럼) 또는 "$@"스칼라 컨텍스트에서(두 번째 예에서처럼) 사용하는 것은 거의 의미가 없습니다. bash셸 에서 스칼라 컨텍스트에서 사용하는 "$@"것은 첫 번째 문자를 공백으로 설정하는 것과 같습니다."$*"$IFS

사용하면 snum=( "$@" )배열이 생성됩니다 snum. 변수에 로 접근하면 $snum배열의 첫 번째 요소를 얻게 됩니다. 실제로는 access 와 동일합니다 ${snum[0]}. "${snum[@]}"유사한 방식으로 개별적으로 참조되는 요소를 제공하는 목록을 사용하십시오 "$@". 를 사용하면 "${snum[*]}"동등한 결과를 얻을 수 있지만 "$*"배열의 경우입니다 snum.

snum위치 인수 목록에서 배열을 생성한 다음 비어 있지 않은 경우 해당 배열을 인쇄 한다고 가정하면 다음을 사용할 수 있습니다.

#!/bin/bash

snum=( "$@" )

if [ "${#snum[@]}" -gt 0 ]; then
    printf '%s\n' "${snum[@]}"
fi

snum스크립트에 인수가 제공되면 요소가 별도의 줄에 인쇄됩니다.

실행 예시:

bash-5.1$ ./script 1 2 3 "hello world" 4
1
2
3
hello world
4

hello world매개변수는 단일 매개변수로 유지됩니다.아니요주변 따옴표를 잊어버리면 이런 일이 발생합니다 $@.

콜론으로 구분된 단일 문자열의 위치 인수 목록을 인쇄합니다. 문자열을 수정하여 위치 매개변수 사이에 콜론을 삽입합니다 $IFS.

#!/bin/bash

IFS=:
snum="$*"

if [ -n "$snum" ]; then
    printf '%s\n' "$snum"
fi

차이점은 snum이제 요소 배열이 아닌 단일 문자열이라는 점입니다. 문자열이 비어 있지 않은 경우, 즉 비어 있지 않은 인수가 하나 이상 스크립트에 제공된 경우 스크립트는 문자열을 출력합니다.

snum또는 계속해서 배열 로 사용되도록 첫 번째 예제를 약간 수정하여 ,

#!/bin/bash

snum=( "$@" )

if [ "${#snum[@]}" -gt 0 ]; then
    IFS=:
    printf '%s\n' "${snum[*]}"
fi

실행 예시:

bash-5.1$ ./script 1 2 3 "hello world" 4
1:2:3:hello world:4

답변2

var=( values )

배열 변수 할당입니다

var=value

는 스칼라 변수 할당입니다(그리고 var="$@"에는 var아래와 같이 위치 인수와 공백을 연결하여 할당됩니다).하나스칼라이기 때문에 문자열입니다)

$var배열의 요소는 인덱스 0의 요소로 확장됩니다. 이는 ${var[0]}배열의 모든 요소에 필요한 것과 동일하며 ${var[@]}Korn 셸에서 복사한 잘못된 디자인입니다.

또한 참고하십시오:

  • Split+glob 연산자는 목록 컨텍스트에서 인용되지 않은 인수 확장을 유지하는데, 이는 거의 원하지 않습니다. 아이러니하게도 위에서 인용문을 추가하는 유일한 곳은 인용문이 필요하지 않은 곳뿐입니다.
  • echo출력의 임의 데이터에는 사용할 수 없습니다 bash.

원하는 곳은 다음과 같습니다.

#! /bin/bash -
print_space_separated() {
  local IFS=' '
  printf '%s\n' "$*"
}

if [ "$#" -gt 0 ]; then
  snum=( "$@" )
  print_space_separated "${snum[@]}"
fi

zshwho 의 배열 설계가 의 배열 설계 보다 가까운 경우 다음을 수행할 수 있습니다.cshksh

#! /bin/zsh -
if (( $# > 0 )) {
  snum=( $argv )
  print -r -- $snum
}

(그 print -r자체는 ksh에서 유래)

그러나 따옴표 없이 배열 확장을 두면 이 셸에서 인수 확장이 발생할 때 분할+glob 없이도 빈 요소가 계속 제거됩니다. 이를 보존하려면 ksh 구문이 필요합니다.

#! /bin/zsh -
if (( $# > 0 )) {
  snum=( "$@" )
  print -r -- "${snum[@]}"
}

( "${snum[@]}"'로 단축할 수도 있지만 "$snum[@]").

in var="$@"또는 에는 var="${array[@]}"in 의 첫 번째 문자 와 공백으로 연결된 var위치 인수로 구성된 문자열이 포함됩니다 . POSIX 지정되지 않은 동작은 참조 및 목록 컨텍스트에서만 사용됩니다. 이식성의 첫 번째 문자와 연결된 위치 인수를 얻으려면 (목록 또는 비목록 컨텍스트에서)를 사용하세요.$IFSzshbash$@$IFS"$*"

배열 요소를 임의의 문자열( 의 첫 번째 문자 제외)과 연결하려면 $IFS: 에서 j매개변수 확장 플래그를 사용하세요. 이에 상응하는 것은 없습니다. 가지다.zsh${(j[that-string])array}bashfishstring join -- that-string $array

관련 정보