Bash数组处理函数调用时的空字节警告问题及declare与typeset的使用疑问
嗨,我来帮你一步步拆解这个问题哈~
一、空字节警告的原因与解决方法
首先,你看到的bash: warning: command substitution: ignored null byte in input警告,根源在于bash的命令替换($(...))无法处理空字节——bash的字符串本身不支持内嵌空字节,当你用命令替换捕获带空字节的输出时,bash只能忽略这些空字节,同时抛出警告提示你。
再看你的代码,还有两个关键问题需要修正:
1. 数组参数传递错误
你现在调用函数的方式是my_func "${ary[@]}" "${seqn[@]}",这会把ary和seqn的数组元素逐个展开成函数参数(总共4个参数),但函数里用declare -n incl="$1" excl="$2"是想绑定到数组变量名,不是数组元素。这会导致incl被绑定到不存在的变量PROGL(因为$1是"PROGL"),完全达不到你传递数组的目的。
正确的做法是直接传递数组名:
my_func ary seqn
2. 函数逻辑与输出方式问题
你函数里的printf '%s\0'位置不对(缩进错误,目前在elif分支里),应该放在循环结束后统一输出。另外,如果你的目标是把函数生成的isufx数组传递出来,不要用命令替换(因为存不了空字节),而是用readarray -d ''来读取空字节分隔的输出:
修正后的完整代码示例:
ary=( "PROGL" "TYPOG" ) seqn=( "THIS" "THAT" ) # 调用函数并读取结果到outa数组 my_func ary seqn | readarray -d '' outa # 定义函数 my_func () { # 绑定传入的数组变量名 declare -n incl="$1" excl="$2" local isufx=() if (( ${#incl[@]} > 0 )); then for ext in "${incl[@]}"; do if [[ "$ext" == "PROGL" ]]; then isufx+=( --include=\*.{rc,el,c,f} ) elif [[ "$ext" == "PEXTD" ]]; then isufx+=( --include=\*.{rc,el,c,f} ) isufx+=( --include=\*.{cp,cpp,f90,f95,f03,f08} ) elif [[ "$ext" == "TYPOG" ]]; then isufx+=( --include=\*.{org,texi,tex} ) fi done # 用空字节分隔输出数组元素 printf '%s\0' "${isufx[@]}" fi }
这样修改后,既解决了空字节警告(用readarray替代命令捕获),也修正了数组传递的逻辑错误。
二、declare vs typeset的使用疑问
在你用的Ubuntu 18.04的bash环境里,typeset和declare是完全等价的——typeset是从ksh shell继承来的别名,bash对其做了兼容支持,功能上没有任何区别。
如果硬要说差异的话:
declare是bash的原生关键字,官方文档里更常用它来举例- 在其他shell(比如zsh)里,两者可能有细微的功能差异,但在bash里完全通用
所以用哪个都可以,看你个人习惯就行,不存在“哪个更好”的说法。
备注:内容来源于stack exchange,提问作者Fatipati

