우리는 일반적으로 $@
$0을 제외한 모든 매개변수를 나타내는 데 사용합니다. 그런데 $@
데이터 구조가 무엇인지 모르겠습니다 .
$*
큰따옴표가 포함되면 다르게 동작하는 이유는 무엇입니까? 누구든지 통역사 수준의 설명을 제공할 수 있습니까?
for 루프에서 반복될 수 있으므로 배열처럼 보입니다. 그러나 이는 simple 과 똑같이 작동합니다 echo $@
. 배열인 경우 첫 번째 요소만 표시됩니다. 셸의 제한으로 인해 수행할 실험 코드를 더 이상 작성할 수 없습니다.
사이의 차이이 게시물: 이 문서에서는 $@
의 동작이 의 동작과 다르다는 것을 보여줍니다 $*
. 하지만 데이터 유형이 혼란 스럽습니다 $@
. Python과 같은 해석 언어인 Shell은 일련의 기본 유형 측면에서 데이터를 표현해야 합니다. 즉, $@이 컴퓨터 메모리에 어떻게 저장되는지 알고 싶습니다.
문자열인가요, 여러 줄 문자열인가요, 아니면 배열인가요?
유일한 데이터 유형인 경우 맞춤 변수를 해당 유형의 인스턴스로 정의할 수 있나요?
답변1
이것은 Bourne 쉘 해킹으로 시작되었습니다. Bourne 셸에서 for
IFS 단어 분할(토큰화 후)은 목록 컨텍스트(명령줄 인수 또는 반복되는 단어)의 모든 단어에 대해 수행됩니다. 당신이 가지고 있다면:
IFS=i var=file2.txt
edit file.txt $var
두 번째 줄은 3개의 단어로 태그가 지정되고 $var
확장되며, 세 단어 모두에 대해 분할+glob이 수행되므로 결국 , , ,를 인수로 ed
사용하여 실행 하게 됩니다.t
f
le.txt
f
le2.txt
그 일부를 인용하면 분할+글로브를 방지할 수 있습니다. Bourne 쉘은 원래 내부적으로 8번째 비트를 설정하여 어떤 문자가 인용되었는지 기억했습니다(나중에 Unix가 8비트로 깔끔해졌을 때 변경되었지만 쉘은 여전히 어떤 바이트가 인용되었는지 기억하는 것과 유사한 작업을 수행했습니다).
둘 다 사이에 공백이 있는 위치 매개변수의 연결 $*
입니다 . $@
그러나 $@
큰따옴표 안에 있는 경우에는 특별하게 처리됩니다. $1
포함 foo bar
및 $2
포함된 경우 baz
다음 "$@"
으로 확장됩니다.
foo bar baz
^^^^^^^ ^^^
( ^
위의 s는 비트 8이 설정된 문자를 나타냅니다.) 여기서 첫 번째 공백은 인용되지만(비트 8이 설정됨) 두 번째 공백(단어 사이에 추가된 공백)은 인용되지 않습니다.
IFS 분할은 인수 분리를 담당합니다( $IFS
기본적으로 공백 문자로 가정). 이는 $*
이전 버전인 Mashey 셸이 확장된 방식 과 유사합니다 (자체는 Thomson 셸을 기반으로 한 반면 Bourne 셸은 처음부터 작성되었습니다).
이는 Bourne 쉘에서 위치 인수 목록이 비어 있는 이유를 설명합니다 ( 빈 위치 매개변수로 "$@"
문제를 해결해야 합니까 ?). ${1+"$@"}
공백 문자가 포함되어 있지 않으면 아무런 효과가 없습니다 "$@"
.$IFS
목적은 인수 목록을 다른 명령에 그대로 전달할 수 있도록 하는 것입니다. 그러나 이는 $IFS
빈 목록, 빈 요소 또는 공백이 포함되지 않은 경우 제대로 작동하지 않습니다(처음 두 문제는 이후 버전에서 결국 수정되었습니다).
POSIX 사양의 기반이 되는 Korn 쉘은 이 동작을 여러 가지 방법으로 변경합니다.
- IFS 분할은 따옴표가 없는 확장 결과에 대해서만 수행됩니다(
edit
위 예와 같은 문자 그대로의 단어에 대해서는 수행되지 않음).file.txt
$*
비어 있으면$@
첫 번째 문자나 공백으로 연결되지만 인용된 연산자의 경우 Bourne 쉘에서와 같이 연결 연산자가 인용 해제되고 인용된 경우 비어 있으면 구분 기호가 아닌 위치 인수가 추가됩니다.$IFS
$IFS
"$@"
"$*"
IFS
- 배열에 대한 지원을 추가하고
${array[@]}
${array[*]}
Bourne을 연상시키지만$*
인덱스$@
1 대신 0에서 시작하고 희박합니다(연관 배열과 유사함). 즉$@
실제로 ksh 배열로 처리 할 수 없음 을 의미합니다(csh
//rc
에 여기서 /는 일반 배열입니다).zsh
fish
yash
$argv
$*
- 빈 요소는 유지됩니다.
"$@"
0 인 경우$#
이제 빈 문자열 대신 빈 문자열로 확장됩니다."$@"
이는 비어 있지 않으면 공백이 없을 때 유효합니다. 비어 있으면 와일드카드 없이 따옴표가 없는 문자열이 단일 인수로 확장됩니다(위치 인수가 공백으로 연결됨).$IFS
IFS
$*
$IFS
ksh93은 위의 나머지 문제를 해결합니다. ksh93에서는 의 값에 관계없이 분리된 위치 인수 목록으로 확장된 $*
다음 목록 컨텍스트에서 추가로 분할+글로브+중괄호 확장되어 첫 번째와 연결됩니다.$@
$IFS
$*
바이트(문자가 아님) of 는 $IFS
값 "$@"
에 관계없이 목록 컨텍스트의 위치 인수 목록으로 확장됩니다 $IFS
. var=$@
in 과 같은 비목록 컨텍스트에서는 $@
의 값이 무엇이든 공백과 연결됩니다 $IFS
.
bash
어레이는 ksh 어레이 이후에 설계되었습니다. 차이점은 다음과 같습니다.
- 인용되지 않은 확장 중에는 중괄호 확장이 없습니다.
- 의 첫 번째 문자는
$IFS
for 바이트를 대체합니다. $*
목록이 아닌 컨텍스트에서 null이 인용되지 않은 경우 확장과 같은 일부 코너 케이스 차이점이 있습니다$IFS
.
POSIX 사양은 매우 모호했지만 이제는 bash 동작을 어느 정도 지정합니다.
ksh
다음과 같은 점에서 일반 배열과 다릅니다 bash
.
- 인덱스는 0 대신 1에서 시작합니다(
"${@:0}"
include 제외$0
(위치 인수가 아니며 쉘 및 함수 정의 방법에 따라 함수 이름이 지정되거나 지정되지 않음)). - 요소를 개별적으로 할당할 수 없습니다.
- 희박하지 않으며 요소를 개별적으로 설정 해제할 수 없습니다.
shift
사용할 수 있습니다.
배열이 zsh
일반 배열인 경우 일반 배열로 처리됩니다 (희소하지 않고 ksh/bash를 제외한 다른 모든 쉘에서 인덱싱이 1부터 시작함). (호환성을 위해) 별칭이 있습니다. or와 동일합니다(인수는 of의 첫 번째 문자와 연결되지만 목록 컨텍스트에서는 별도로 유지됩니다). 코헨과 유사하거나 특수 가공된 제품입니다.yash
$*
zsh
$argv
csh
$*
$argv
${argv[*]}
$IFS
"$@"
"${argv[@]}"
"${*[@]}"}
답변2
$@
그런데 데이터 구조가 무엇인지 모르겠습니다 .
이는 위치 매개변수의 값으로 확장될 수 있는 특수 매개변수입니다. 하지만 용어가 까다롭습니다.
위치 인수를 a의 일부로 생각할 수 있으므로 독립적으로 액세스할 수 있고 연속된 자연수로 이름을 지정할 수 있는 $@
다양한 요소( $1
, ...)가 있습니다. $2
이는 일반적으로 배열로 알려져 있습니다.
하지만 구문은 약간 이상하고 제한적입니다. 배열의 개별 요소는 개별적으로 수정할 수 없습니다. 대신 모든 것을 한 번에 설정해야 합니다. ( set -- "$@" foo
추가된 값을 사용할 수도 있고 , set -- "${@:1:2}" foo "${@:3}"
중간에 값을 추가할 수도 있습니다. 하지만 두 경우 모두 결과 목록 전체를 작성해야 합니다.)
$*
큰따옴표를 포함할 때와 다르게 동작하는 이유는 무엇입니까 ?
그들의 행동이 다르게 정의되기 때문입니다.
그러나 이는 simple 과 똑같이 작동합니다
echo $@
. 배열인 경우 첫 번째 요소만 표시됩니다.
a=(foo bar asdf); echo $a
단지 출력을 의미한다면 foo
이는 대부분 쉘 구문의 특이한 점이며 ksh 스타일 명명된 배열은 위치 인수 및 $@
. Plain $a
은 동일하므로 배열이든 단순 스칼라 변수 ${a[0]}
이든 단일 스칼라 값에 대해 이전 버전과 호환되는 의미를 갖습니다 .a
@
전체 목록을 참조하는 기호는 명명된 배열과 함께 재사용되며, 이것이 "${a[@]}"
전체 목록을 얻는 방법입니다. 명명된 배열과 비교하여 with 를 사용하면 $@
불필요한 중괄호와 대괄호, 이름이 생략됩니다.
혹은 즉,
$@
컴퓨터 메모리에 어떻게 저장되는지 알고 싶습니다.
이는 구현에 따라 다르며 관심 있는 특정 셸에 대한 소스 코드를 살펴봐야 합니다.
문자열인가요, 여러 줄 문자열인가요, 아니면 배열인가요?
주로 배열입니다. ksh 스타일의 명명된 배열과 달리 연속된 정수뿐만 아니라 음수가 아닌 임의의 정수를 인덱스로 가질 수 있습니다 $@
. (즉, 명명된 배열은 희박할 수 있으며, 예를 들어 indexes 1
, 3
, 4
, with 0
및 2
누락 등을 가질 수 있습니다. 이는 위치 인수로는 불가능합니다.)
다른 요소로 확장될 수 있기 때문에 단일 문자열이 아니며 일반 변수 또는 위치 인수 중 하나( 요소 $@
)에도 개행 문자가 포함될 수 있으므로 line 요소 호출도 올바르지 않습니다.
유일한 데이터 유형인 경우 맞춤 변수를 해당 유형의 인스턴스로 정의할 수 있나요?
아니요. 하지만 명명된 배열이 더 유용할 수 있습니다.