eval 与 echo 一起使用

eval 与 echo 一起使用

我想知道下面的代码是否可以改进它的编写方式。如果不清楚,我是 Bash 的新手,但我的脚本完成了它的目的。

此代码尝试s$counter= s1, s2, s3, s4...根据先前定义的变量s1$j以及s2$j作为j列表项的字符串(均先前定义)来定义变量。

counter=1 
for j in ${list[@]}
    do
            eval s$counter=$(eval "echo \$s1$j")
            eval s$((counter+1))=$(eval "echo \$s2$j")
            counter=$((counter+2))
    done

内部的eval,意思$(eval "echo \$s1$j")是 es ,用于返回 的值s1$j。第二个eval,意思是 eval ,s$counter =...用于定义变量s1, s2, s3, s4 ...

j=a因此,举个例子:假设对于第一个 foor 循环$(eval "echo \$s1$j") == $s1a,其值s1a 在脚本中先前定义,例如让它为“ s1a=10”,以便在eval评估第二个时,我们得到声明“ ”的命令s1=10

它可以起作用,但是否会发生一些事情,从而导致可能的内存威胁或类似的事情?

这行代码的思路是一样的。

eval $(echo "sed -i '$(eval echo '17i$sed17line')' $file")

sed17line我要在 的第 17 行中添加的内容在哪里file。这取决于我想要使用该脚本做什么,这就是我将其用作变量的原因,因此我使用了echo和的组合eval

答案1

意识到存在问题是件好事eval) 和echo这里)。您应该避免使用eval,因为它很容易被误用。

即使这些命令在您的特定情况下是完全安全的,我还是建议您放弃eval。您的代码确实因此过于复杂。


有了数组,您的第一个示例会变得更加简洁。这在我的 Debian 中的 GNU bash 4.4.12 中有效:

# preparing variables
unset -v list s s1 s2
declare -a list=( foo 'X Y' bar baz )
declare -a s
declare -A s1=( [foo]='FOO 1' [bar]='BAR 2' [baz]='BAZ beep; eject /dev/sr0' )
declare -A s2=( [foo]='oof oof' [bar]='rab rab' [baz]='zab zab' [X Y]='9')

# your code rewritten, we don't even need a counter
for j in "${list[@]}"
  do
    s+=( "${s1[$j]}" "${s2[$j]}" )
  done

# checking contents of s
printf '%s\n' "${s[@]}"

提示:研究“索引数组”、“关联数组”及其用法bash

注意,带空格的元素(X Y)对我来说没什么特别的;但它会破坏你的代码。我也可以BAZ beep; eject /dev/sr0在我的 中有s1;我敢说你会在你的数组中设置s1baz='BAZ beep; eject /dev/sr0',执行你的代码,看看会发生什么。这就是的能力。现在想象一下我把代替。bazlistevalrm -rf ~/eject …


第二个示例可以大大简化为:

sed -i "17i$sed17line" "$file"

eval您似乎对+有偏见,echo因为您创建了一个在不需要时使用两次 + 的装置。可能是因为您的变量并不总是在您需要时扩展为它们的值;如果是这样,请研究 中单引号 ( ') 和双引号 ( ")之间的区别bash

感谢您提出疑问并提问。

相关内容