2012-02-05 43 views
0

这里是我的问题的最简单的蒸馏版本。即使在这里不是很明显,仍然存在的复杂性是有充分理由的。另外脚本是内部的,没有执行恶意代码的机会,所以eval是完全正确的;不需要知道它是多么邪恶......;)暂时假定键字符串中的管道和冒号是必需的分隔符。bash,eval,保护管道和冒号字符串

key="target|platform|repo:revision" 
hashname="hashmap" 
declare -A $hashname 

eval $hashname[$key]=0 
echo $(eval $hashname[$key]) 

当然,最后两行有问题,因为eval作用于$ key变量的管道和冒号。我的问题是如何从eval保护这样的字符串?我需要eval,因为我指的是hashmap的名称而不是它本身。提前致谢。

============================================== ====================================

好吧我其实开始认为我的问题是不是与管道和冒号和eval。所以让我贴实际的代码

function print_hashmap() 
{ 
    local hashname=$1 
    for key in `eval echo \$\{\!$hashname[@]\}`; do 
     local deref="$hashname[$key]" 
     local value=${!deref} 
     echo "key=${key} value=${value}" 
    done 
} 
function create_permutations2() 
{ 
    local hashname=$1 ; shift 
    local builds=$1  ; shift 
    local items=$1  ; shift 
    local [email protected] 

    echo "create_permutations(hashname=${hashname}, builds=${builds}, items=${items}, separators=${separators})" 

    if [ NULL != "${builds}" ]; then 
     for build in `echo $builds | tr ',' ' '`; do 
      local target="${build%%:*}" 
      local platforms="${build##*:}" 
      for platform in `echo $platforms | tr '|' ' '`; do 
       local key= 
       local ref= 
       if [ NULL != "${items}" ]; then 
        if [ NULL == "${separators}" ]; then separators=' '; fi 
        for separator in $separators; do 
         items=`echo $items | tr $separator ' '` 
        done 
        for item in $items; do 
         key="${target}|${platform}|${item}" 
         ref="$hashname[$key]" 
         declare "$ref"=0 
        done 
       else 
        key="${target}|${platform}" 
        ref="$hashname[$key]" 
        declare "$ref"=0 
       fi 
      done 
     done 
    fi 

    echo "created the following permutations:" 
    print_hashmap $hashname 
} 
builds="k:r|s|w,l:r|s|w" 
repos="c:master,m:master" 
hashname="hashmap" 
declare -A $hashname 

create_permutations2 $hashname $builds $repos "," 
print_hashmap $hashname 

我最近修改了代码FatalError的建议使用参考,而不是EVAL和错误,以符合是相同的:在表达式语法错误(错误标记附近:主)

+0

你有没有试过逃脱管道字符?例如:'\ |'而不是'|' – Gigi 2012-02-05 19:03:52

+0

是的;那不起作用 – 2012-02-05 19:21:27

+0

你想做什么?这不是你如何访问数组成员 – Kevin 2012-02-05 19:29:29

回答

2

也许双打报价大约$key

eval $hashname["$key"]=0 
echo $(eval $hashname["$key"]=0) 
0

我不会讲授的eval的邪恶,但是在这种情况下,它至少增加了一些额外的复杂性。我能想到的,因为它的评估字符串结果最简单的方法,将添加一些文字单引号:

eval $hashname["'"$key"'"]=0 

这将防范除了在$key单引号的一切。然而,你可以用更少的头痛来完成同样的事情。这里是我的更新脚本来说明:

key="target|platform|repo:revision" 
hashname="hashmap" 
declare -A $hashname 

echo "With eval:" 
eval $hashname["'"$key"'"]=0 
eval echo \${$hashname["'"$key"'"]} 
echo 

echo "Without eval:" 
ref="$hashname[$key]" 
echo ${!ref} 
declare "$ref"="1" 
echo ${!ref} 

注意我改变了原来的eval线,因为它没有任何意义,我 - 这是尝试执行的结果,而不是打印出来。在后一部分中,您可以使用间接方式访问该值,然后使用declare进行分配。那么你不必担心这些字符被解释。

这产生的结果:

With eval: 
0 

Without eval: 
0 
1 

我不是100%肯定,为什么不工作,但这似乎:

builds="k:r|s|w,l:r|s|w" 
repos="c:master,m:master" 
hashname="hashmap" 
declare -A $hashname 

function print_hashmap() 
{ 
    local hashname=$1 
    for key in `eval echo \$\{\!$hashname[@]\}`; do 
     local deref="$hashname[$key]" 
     local value=${!deref} 
     echo "key=${key} value=${value}" 
    done 
} 
function create_permutations2() 
{ 
    local hashname=$1 ; shift 
    local builds=$1  ; shift 
    local items=$1  ; shift 
    local [email protected] 

    echo "create_permutations(hashname=${hashname}, builds=${builds}, items=${items}, separators=${separators})" 

    if [ NULL != "${builds}" ]; then 
     for build in `echo $builds | tr ',' ' '`; do 
      local target="${build%%:*}" 
      local platforms="${build##*:}" 
      for platform in `echo $platforms | tr '|' ' '`; do 
       local key= 
       if [ NULL != "${items}" ]; then 
        if [ NULL == "${separators}" ]; then separators=' '; fi 
        for separator in $separators; do 
         items=`echo $items | tr $separator ' '` 
        done 
        for item in $items; do 
         key="${target}|${platform}|${item}" 
         ref="$hashname[$key]" 
         eval $hashname[\'$key\']=0 
        done 
       else 
        key="${target}|${platform}" 
        eval $hashname[\'$key\']=0 
       fi 
      done 
     done 
    fi 

    echo "created the following permutations:" 
    print_hashmap $hashname 
} 

create_permutations2 $hashname $builds $repos "," 
print_hashmap $hashname 
+0

我不介意使用没有eval的解决方案,因为您已经在这里演示了。我会试着看看我是否能够解决我现实世界的问题。然而,你能解释你的倒数第二行:宣布“$ ref”=“1”?为什么报价和为什么申报?并且在1周围需要引号? – 2012-02-05 19:58:10

+0

我修改了我原来的帖子,以包含生产代码和导致行为的示例用法。我实施了你的建议并得到相同的错误。 – 2012-02-05 20:18:10

+0

'1'周围的引言不会做任何事 - 只是我的习惯。在'$ ref'周围的引用在这里并不重要,但是如果你的密钥包含空格的话。 – FatalError 2012-02-05 20:18:43

0

尝试:

eval $hashname'[$key]'=0 
eval result=$hashname'[$key]' 

这通过$eval而不是首先扩展参数。