首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不使用eval的间接寻址

不使用eval的间接寻址
EN

Stack Overflow用户
提问于 2012-11-24 21:02:04
回答 1查看 197关注 0票数 2

我正在寻找一种干净的方法(不使用eval命令)来间接引用数组。下面是我想要的更精确的描述:

代码语言:javascript
复制
function valueof {
   echo "indirection1 \$$1=${!1}"
   eval "echo indirection2 \\\$$1=\${$1[@]}" # Untill this step its fine.

   # My final objective is to do this (but eval is not a very sexy solution) : 
   for i in $(eval "echo \${$1[@]}") ; do 
      echo $i
   done

   # Here is the "problem", ie. "bad substitution"
   echo "indirection3 \$$1=${!1[@]}"  
   # "1[@]" is evaluated first i guess?
}

具有以下调用值:

代码语言:javascript
复制
a=("a" "aa" "aaa")
b=("b" "bb" "bbb")
valueof a
valueof b

我得到的输出是:

代码语言:javascript
复制
indirection1 $a=a
indirection2 $a=a aa aaa
a
aa
aaa
indirection1 $b=b
indirection2 $b=b bb bbb
b
bb
bbb

在stderr上:

代码语言:javascript
复制
prog.sh: line 10: indirection3 $1=${!1[@]}: bad substitution
prog.sh: line 10: indirection3 $1=${!1[@]}: bad substitution

感谢您对此问题的回答/评论:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-25 00:13:16

我建议从git devel分支构建Bash,并使用typeset -n,就像大多数其他具有数组的正常shell一样。所有其他涉及函数和数组的解决方案要么需要eval,要么需要利用奇怪的未记录行为。两者都需要同等的注意,并且两者之间不一定有优势。

下面是一个通用的示例,它演示了几乎所有可以在不使用eval的情况下间接执行的操作。命名空间冲突仍然是可能的。

代码语言:javascript
复制
isSubset() {
    local -a 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'
    set -- "${@/%/[key]}"

    (( ${#xkeys[@]} <= ${#ykeys[@]} )) || return 1

    local key
    for key in "${xkeys[@]}"; do
        [[ ${!2+_} && ${!1} == "${!2}" ]] || return 1
    done
}

a=(abc def [4]=ghi jkl)
b=(abc def [4]=ghi jkl)
c=(abc [3]=def [6]=ghi xyz)
isSubset a b
echo $? # 0
isSubset b c
echo $? # 1

在某些方面,这实际上是伪装的eval。大多数人没有意识到,当他们将变量名传递给内置和算术表达式时,他们就是在有效地执行eval。您必须始终确保变量名称和索引是由内部控制的,并且永远不会受到用户输入或其他无法保证结果的副作用的影响。

从你对分词和引号的误用来看,你应该换一种不同的语言。Bash实际上不是用来处理安全封装的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13541465

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档