ProgramingTip

Bash 완성의 맥락에서 $ {array [*]}와 $ {array [@]}에 대한 혼동

bestdevel 2020. 11. 4. 08:12
반응형

Bash 완성의 맥락에서 $ {array [*]}와 $ {array [@]}에 대한 혼동


나는 처음으로 Bash 완성을 작성하는 데 찌르고 많이 Bash 배열 ( ${array[@]}${array[*]}) 을 역 참조하는 두 가지 방법에 약간 혼란 스럽습니다 .

다음은 관련 코드 덩어리입니다 (그런데 작동하지만 더 잘 이해하고 싶습니다).

_switch()
{
    local cur perls
    local ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
    COMPREPLY=()
    cur=${COMP_WORDS[COMP_CWORD]}
    perls=($ROOT/perls/perl-*)
    # remove all but the final part of the name
    perls=(${perls[*]##*/})

    COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/perl" -- ${cur} ) )
}

Bash의 문서에 따르면 다음과 가변 합니다.

배열의 모든 요소는 $ {name [subscript]}를 사용하여 참조 할 수 있습니다. 셸의 파일 이름 확장 연산자와의 충돌을 방지하기 위해 중괄호가 필요합니다. 아래 첨자가 '@'또는 '*'이면 단어는 배열 이름의 모든 멤버로 확장됩니다. 이 아래에 첨자는 단어가 큰 따옴표로 묶인 경우에만. 단어가 큰 따옴표 인 경우 $ {name [*]}은 각 배열 구성원의 값이 IFS 변수의 첫 번째 문자로 구분 된 단일 단어로 확장되고 $ {name [@]}은 이름의 각 요소를 확장합니다. 별도의 단어로.

이제 compgen -W가능한 대안의 단어 목록이 포함 된 문자열 예상 된다는 것을 이해한다고 생각 합니다. "$ {name [@]}이 이름의 각 요소를 별도의 단어로 확장합니다"가 의미하는 바를 이해하지 못합니다.

짧은 이야기 : ${array[*]}작품; ${array[@]}하지 않습니다. 그 이유를 알고 싶습니다 ${array[@]}. 정확히 무엇이 확장 되고 더 잘 이해하고 싶습니다 .


(이 Kaleb 페더슨의 대답에 내 의견의 확장이다-의보다 일반적인 치료를 위해 그 답을 [@][*].)

bash (혹은 척 셸)가 명령 줄을 구문 분석 할 때 혼동의 "단어"(나중에 혼동을 피하기 "셸 단어"부름)로 분할합니다. 일반적으로 쉘 단어는 공백 (또는 기타 공백)으로 공백은 이스케이프 또는 인용을 통해 쉘 단어에 사용할 수 있습니다. 큰 따옴표로 묶인 배열 [@][*]확장 배열 의 차이점은 배열의 각 "${myarray[@]}"요소가 별도의 셸 단어로 처리되는 반면 "${myarray[*]}"배열의 셸 단어 가 공백으로 구분 된 셸 단어가됩니다 (또는의 첫 문자가 무엇이든 IFS).

일반적으로 [@]행동은 당신이 원하는 것입니다. 우리가 가지고 있고 perls=(perl-one perl-two)사용 하는 가정 ls "${perls[*]}"합니다 ls "perl-one perl-two". 이것은 단일 파일을 단일 파일을 perl-one perl-two것입니다. ls "${perls[@]}"상당이다 ls "perl-one" "perl-two"훨씬 더 가능성이있는 일을 할 것입니다.

완성 된 단어 목록 (셸 단어와의 혼동을 피하기 위해 comp-words라고 부름)을 제공하는 compgen것입니다. -W옵션은 comp-word 목록을 가져 오기 오지만, comp-word가 공백으로 구분 된 단일 쉘-워드 형식이어야합니다. 항상 (적어도 내가 아는 한) 인수를받는 명령 옵션은 단일 쉘 단어를 사용합니다. 정렬 옵션에 대한 인수가 언제 끝나는 지 알 수있는 방법이 일반 명령 인수 (/ other 옵션 플래그) 시작합니다.

더 자세하게 :

perls=(perl-one perl-two)
compgen -W "${perls[*]} /usr/bin/perl" -- ${cur}

다음과 달라집니다.

compgen -W "perl-one perl-two /usr/bin/perl" -- ${cur}

... 당신이 원하는 것을. 반면에

perls=(perl-one perl-two)
compgen -W "${perls[@]} /usr/bin/perl" -- ${cur}

다음과 달라집니다.

compgen -W "perl-one" "perl-two /usr/bin/perl" -- ${cur}

... 완전한 말도 안되는 말입니다. "perl-one"은 -W 플래그에 첨부 된 유일한 comp-word이고, compgen이 완성 될 것입니다. 첫 번째 실제는 "perl-two"입니다. / usr / bin / perl "입니다. 나는 compgen이 추가 인수 ("- "및 $ cur에있는 모든 것)가 주어 졌다고 불평 할 것으로 예상하지만 무시합니다.


은 제목 ${array[@]}-to- 에 대해 ${array[*]}묻지 만 어느 $array[*]-to- 에 대해 물어 보는 $array[@]것이 약간 혼란 스럽습니다. 나는 둘 다 대답 할 것이다 :

배열 변수를 인용 @하고 아래에 첨자로 사용하면 배열의 $IFS요소는 해당 콘텐츠 확장 서열 수있는 공백 (실제로는 하나 )에 관계없이 전체 콘텐츠로 됩니다. 별표 ( *)를 아래 첨자로 사용하면 ( 인용 여부에 관계없이)에서 각 배열 요소의 콘텐츠를 분할하여 새 콘텐츠로 확장 할 수 있습니다 $IFS.

다음은 예제 펼쳐입니다.

#!/bin/sh

myarray[0]="one"
myarray[1]="two"
myarray[3]="three four"

echo "with quotes around myarray[*]"
for x in "${myarray[*]}"; do
        echo "ARG[*]: '$x'"
done

echo "with quotes around myarray[@]"
for x in "${myarray[@]}"; do
        echo "ARG[@]: '$x'"
done

echo "without quotes around myarray[*]"
for x in ${myarray[*]}; do
        echo "ARG[*]: '$x'"
done

echo "without quotes around myarray[@]"
for x in ${myarray[@]}; do
        echo "ARG[@]: '$x'"
done

다음은 출력입니다.

with quotes around myarray[*]
ARG[*]: 'one two three four'
with quotes around myarray[@]
ARG[@]: 'one'
ARG[@]: 'two'
ARG[@]: 'three four'
without quotes around myarray[*]
ARG[*]: 'one'
ARG[*]: 'two'
ARG[*]: 'three'
ARG[*]: 'four'
without quotes around myarray[@]
ARG[@]: 'one'
ARG[@]: 'two'
ARG[@]: 'three'
ARG[@]: 'four'

나는 개인적으로 보통 원한다 "${myarray[@]}". 이제, 질문의 두 번째 부분에 대답 ${array[@]}$array[@].

인용 한 bash 문서를 인용합니다.

셸의 파일 이름 확장 연산자와의 충돌을 방지하기 위해 중괄호가 필요합니다.

$ myarray=
$ myarray[0]="one"
$ myarray[1]="two"
$ echo ${myarray[@]}
one two

그러나 그렇게 할 때 $myarray[@]달러 기호는 단단히 묶여 myarray있으므로 [@]. 예를 들면 :

$ ls $myarray[@]
ls: cannot access one[@]: No such file or directory

그러나 문서에서 언급했듯이 대괄호는 파일 이름 확장을위한 것이므로 다음을 시도해보십시오.

$ touch one@
$ ls $myarray[@]
one@

이제 확장 후 파일 이름 확장이 발생했음을 알 수 있습니다 $myarray.

그리고 $myarray아래 첨자가없는 또 하나의 메모 는 배열의 첫 번째 값으로 확장됩니다.

$ myarray[0]="one four"
$ echo $myarray[5]
one four[5]

참고 URL : https://stackoverflow.com/questions/3348443/a-confusion-about-array-versus-array-in-the-context-of-a-bash-comple

반응형