Bash中的懒惰评估

时间:2010-05-24 22:16:12

标签: bash lazy-evaluation

是否有比下面更优雅的懒惰评估方式:

pattern='$x and $y'
x=1
y=2
eval "echo $pattern"

结果:

1 and 2

它有效,但eval "echo ..."只是感觉草率,可能在某种程度上不安全。在Bash中有更好的方法吗?

3 个答案:

答案 0 :(得分:5)

您可以使用envsubst中的gettext命令,例如:

$ pattern='$x and $y'
$ x=1 y=2 envsubst <<< $pattern
1 and 2

答案 1 :(得分:4)

一种安全的可能性是使用功能:

expand_pattern() {
    pattern="$x and $y"
}

这就是全部。然后使用如下:

x=1 y=1
expand_pattern
echo "$pattern"

您甚至可以使用xy作为环境变量(以便它们不在主范围中设置):

x=1 y=1 expand_pattern
echo "$pattern"

答案 2 :(得分:0)

你是对的,eval在这种情况下是一种安全风险。这是一种可能的方法:

pattern='The $a is $b when the $z is $x $c $g.'    # simulated input from user (use "read")
unset results
for word in $pattern
do
    case $word in
        \$a)
            results+=($(some_command))   # add output of some_command to array (output is "werewolf"
            ;;
        \$b)
            results+=($(echo "active"))
            ;;
        \$c)
            results+=($(echo "and"))
            ;;
        \$g)
            results+=($(echo "the sky is clear"))
            ;;
        \$x)
            results+=($(echo "full"))
            ;;
        \$z)
            results+=($(echo "moon"))
            ;;
          *)
            do_something    # count the non-vars, do a no-op, twiddle thumbs
            # perhaps even sanitize %placeholders, terminal control characters, other unwanted stuff that the user might try to slip in
            ;;
    esac
done
pattern=${pattern//\$[abcgxz]/%s}    # replace the vars with printf string placeholders
printf "$pattern\n" "${results[@]}"  # output the values of the vars using the pattern
printf -v sentence "$pattern\n" "${results[@]}"  # put it into a variable called "sentence" instead of actually printing it

输出将是“当月亮充满且天空晴朗时狼人活跃。”同样的程序,如果模式是'$ x $ z超出$ c $ g,那么$ a必须是$ b。'然后输出将是“满月出来,天空晴朗,所以狼人必须活跃。”