들어 bash는 , 그것은 (문서화이기는하지만) 해킹의 약간의 : 사용하려고은 typeset
은 "배열"속성을 제거하려면 :
$ typeset +a BASH_VERSINFO
bash: typeset: BASH_VERSINFO: cannot destroy array variables in this way
echo $?
1
(에서 할 수는 없으며 명시 적으로 금지 된 zsh
배열을 스칼라로 변환 할 수 있습니다 bash
.)
그래서:
typeset +A myvariable 2>/dev/null || echo is assoc-array
typeset +a myvariable 2>/dev/null || echo is array
또는 마지막에주의 사항을 지적하면서 기능 :
function typeof() {
local _myvar="$1"
if ! typeset -p $_myvar 2>/dev/null ; then
echo no-such
elif ! typeset -g +A $_myvar 2>/dev/null ; then
echo is-assoc-array
elif ! typeset -g +a $_myvar 2>/dev/null; then
echo is-array
else
echo scalar
fi
}
typeset -g
(bash-4.2 이상) 의 사용에 유의하십시오 .이 기능은 typeset
(syn. declare
)이 작동하지 않고 local
검사하려는 값을 방해 하지 않도록 함수 내에서 필요합니다 . 이것은 함수 "가변"유형도 처리하지 않으며, typeset -f
필요한 경우 다른 분기 테스트를 추가 할 수 있습니다 .
또 다른 (거의 완전한) 옵션은 다음을 사용하는 것입니다.
${!name[*]}
If name is an array variable, expands to the list
of array indices (keys) assigned in name. If name
is not an array, expands to 0 if name is set and
null otherwise. When @ is used and the expansion
appears within double quotes, each key expands to a
separate word.
한 가지 작은 문제가 있지만 단일 첨자가 0 인 배열은 위의 두 조건과 일치합니다. 이것은 mikeserv도 참조하는 것으로, bash는 실제로 큰 차이가 없으며, (Changelog를 확인하면) 이것 중 일부는 ksh에 대한 비난과 비 배열에 대한 행동 ${name[*]}
또는 ${name[@]}
비 호환성에 대한 책임이 있습니다 .
따라서 부분적인 해결책은 다음과 같습니다.
if [[ ${!BASH_VERSINFO[*]} == '' ]]; then
echo no-such
elif [[ ${!BASH_VERSINFO[*]} == '0' ]]; then
echo not-array
elif [[ ${!BASH_VERSINFO[*]} != '0' ]];
echo is-array
fi
나는 과거에 이것에 대한 변형을 사용했다 :
while read _line; do
if [[ $_line =~ ^"declare -a" ]]; then
...
fi
done < <( declare -p )
그래도 서브 쉘이 필요합니다.
유용한 기술 중 하나는 compgen
다음과 같습니다.
compgen -A arrayvar
여기에는 모든 인덱스 배열이 나열되지만 연관 배열은 특별하게 (bash-4.4까지) 처리되지 않으며 일반 변수 ( compgen -A variable
) 로 나타납니다.