以下のための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
。必要に応じて別のブランチテストを追加できます。
もう1つの(ほぼ完全な)オプションは、これを使用することです。
${!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.
ただし、1つの小さな問題があります。1つの添え字が0の配列は、上記の2つの条件に一致します。これはmikeservが参照するものでもあり、bashには実際に明確な区別はありません。また、この一部(変更ログを確認する場合)は、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 )
ただし、これもサブシェルが必要です。
もう1つの有用なテクニックはcompgen
次のとおりです。
compgen -A arrayvar
これにより、すべてのインデックス付き配列がリストされますが、連想配列は特別に処理されず(bash-4.4まで)、通常の変数として表示されます(compgen -A variable
)