由于Bash在set -o nounset模式(aka set -u)中运行时 可能会认为空数组未设置,无论它们是否实际上已分配了空值,因此在尝试扩展数组时必须小心 - 其中一个解决方法是检查数组长度是否为零.更不用说获取数组中的元素数量本身就是一种常见的操作.
在openSUSE 42.1中使用Bash 4.2.47(1) - release发展时,我习惯于${#ARRAY_NAME[@]}在数组为空或未设置时获得成功的数组大小 .但是,在FreeBSD 10.3中使用Bash 4.3.46(1)-release检查我的脚本时,结果发现此操作可能会失败并显示通用的"未绑定变量"错误消息.提供扩展的默认值似乎不适用于数组长度.提供替代命令链似乎有效,但不能在通过子shell扩展调用的函数内部 - 函数只在第一次失败后退出.还有什么可以帮到这里?
请考虑以下示例:
function Size ()
{
declare VAR="$1"
declare REF="\${#${VAR}[@]}"
eval "echo \"${REF}\" || echo 0" 2>/dev/null || echo 0
}
set -u
declare -a MYARRAY
echo "size: ${#MYARRAY[@]}"
echo "size: ${#MYARRAY[@]-0}"
echo "Size: $(Size 'MYARRAY')"
echo -n "Size: "; Size 'MYARRAY'
Run Code Online (Sandbox Code Playgroud)
在openSUSE环境中,所有echo行都0按预期输出 .在FreeBSD中,同样的结果是唯一可能当该阵列被显式分配一个空值:MYARRAY=(); 否则,前两行中的内联查询都会失败,第三行只是输出Size:(意味着扩展结果为空),只有最后一行完全由于外部成功|| echo 0 - 但是将结果传递到屏幕不是什么通常在尝试获取数组长度时使用.
以下是我的观察摘要:
Bash 4.2 Bash 4.3
openSUSE FreeBSD
counting elements of unset array OK FAILED
counting elements of empty array OK OK
content expansion of unset array FAILED FAILED
content expansion of unset array(*) OK OK
content expansion of empty array FAILED FAILED
content expansion of empty array(*) OK OK
(* with fallback value supplied)
Run Code Online (Sandbox Code Playgroud)
对我来说,这看起来很不一致.有没有真正面向未来的跨平台解决方案呢?
作为\xc2\xa0临时解决方案,我\xc2\xa0遵循\xc2\xa0@william-pursell建议的\xc2\xa0路线,并且\xc2\xa0只是在\xc2\xa0查询nounset期间取消设置\xc2\xa0选项:
function GetArrayLength ()\n{\n declare ARRAY_NAME="$1"\n declare INDIRECT_REFERENCE="\\${#${ARRAY_NAME}[@]}"\n case "$-" in\n *\'u\'*)\n set +u\n eval "echo \\"${INDIRECT_REFERENCE}\\""\n set -u\n ;;\n *)\n eval "echo \\"${INDIRECT_REFERENCE}\\""\n ;;\n esac\n}\nRun Code Online (Sandbox Code Playgroud)\n\n(使用if而不是 \xc2\xa0case会导致 \xc2\xa0 在 \xc2\xa0my 测试机器上的执行速度明显减慢。此外,case如果 \xc2\xa0 有时有必要,则可以轻松匹配其他选项。)
我还尝试利用\xc2\xa0事实,即使对于\xc2\xa0unset数组,内容扩展(使用回退或\xc2\xa0替换值)通常也会成功:
\n\nfunction GetArrayLength ()\n{\n declare ARRAY_NAME="$1"\n declare INDIRECT_REFERENCE="${ARRAY_NAME}[@]"\n if [[ -z "${!INDIRECT_REFERENCE+isset}" ]]; then\n echo 0\n else\n INDIRECT_REFERENCE="\\${#${ARRAY_NAME}[@]}"\n eval "echo \\"${INDIRECT_REFERENCE}\\""\n fi\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然而,事实证明,Bash 并没有优化${a[@]+b}扩展,因为 \xc2\xa0 对于较大的数组 \xc2\xa0\xe2\x80\x94 来说,执行时间明显增加,尽管是 \xc2\xa0 中最小的一个\xa0empty 或\xc2\xa0unset 数组。
尽管如此,如果\xc2\xa0任何人有\xc2\xa0更好的解决方案,请随意\xc2\xa0发布其他答案。
\n| 归档时间: |
|
| 查看次数: |
602 次 |
| 最近记录: |