我想知道下面的代码是否可以改进它的编写方式。如果不清楚,我是 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'
,执行你的代码,看看会发生什么。这就是的能力。现在想象一下我把代替。baz
list
eval
rm -rf ~/
eject …
第二个示例可以大大简化为:
sed -i "17i$sed17line" "$file"
eval
您似乎对+有偏见,echo
因为您创建了一个在不需要时使用两次 + 的装置。可能是因为您的变量并不总是在您需要时扩展为它们的值;如果是这样,请研究 中单引号 ( '
) 和双引号 ( "
)之间的区别bash
。
感谢您提出疑问并提问。