Bash 中的惰性求值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2900707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:07:53  来源:igfitidea点击:

Lazy Evaluation in Bash

bashlazy-evaluation

提问by User1

Is there more elegant way of doing lazy evaluation than the following:

是否有比以下更优雅的惰性评估方式:

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

results:

结果:

1 and 2

It works but eval "echo ..."just feels sloppy and may be insecure in some way. Is there a better way to do this in Bash?

它有效,但eval "echo ..."只是感觉马虎,并且可能在某些方面不安全。有没有更好的方法在 Bash 中做到这一点?

采纳答案by tokland

You can use the command envsubstfrom gettext, for example:

您可以使用命令envsubstgettext的,例如:

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

回答by gniourf_gniourf

One safe possibility is to use a function:

一种安全的可能性是使用一个函数:

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

That's all. Then use as follows:

就这样。然后使用如下:

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

You can even use xand yas environment variables (so that they are not set in the main scope):

您甚至可以使用xy作为环境变量(这样它们就不会在主范围内设置):

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

回答by Paused until further notice.

You're right, evalis a security risk in this case. Here is one possible approach:

你是对的,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

The output would be "The werewolf is active when the moon is full and the sky is clear." The very same program, if the pattern is 'The $x $z is out $c $g, so the $a must be $b.' then the output would be "The full moon is out and the sky is clear, so the werewolf must be active."

输出将是“狼人在满月且天空晴朗时处于活动状态。” 完全相同的程序,如果模式是“$x $z 出 $c $g,所以 $a 必须是 $b。” 然后输出将是“满月出来,天空晴朗,所以狼人一定是活跃的。”