如果条件在一定范围内(边界)有两个不同的值

如果条件在一定范围内(边界)有两个不同的值

假设我有一个坐标 (x,y),我想将其分为两个类别:好或坏。

我不知道如何用文字或关键词来表达它,所以我创建了一个我想要的例子。

我创建了一个这样的 bash 脚本:

x=3.5 #(example)
y=-2.5 #(example)
if [ $x -ge 0.1 -a $x -le 5.5 ] && [ $y -ge -5.9 -a $y -le -0.1 ]; then cat="good";
elif [ $x -ge 5.5 -a $x -le 10.5 ] && [ $y -ge -10.9 -a $y -le -5.9 ]; then cat="bad";
fi
echo "$cat"

在该脚本中,我想知道 x 是否在 0.1 到 5.5 范围内(0.1 < x < 5.5)且 y 是否在 -5.9 到 -0.1 范围内(-5.9 < y < -0.1)为真,则结果为good。使用不同的边界,它应该会给出bad结果。

我已经运行它并且它给出的结果与预期的整数表达式一致。

当我尝试用运算符-ge(或-le)替换运算符>(或<),或者尝试添加方括号和任何我能想到的内容时,它会出现相同的错误或没有给出任何结果。

我该如何处理这个问题?

答案1

Bash 只能进行整数运算。如果值的小数位数是固定的,则可以删除.(使用sedawk或任何您喜欢的命令)并比较结果值。例如,如果它们只有一位小数,如 ,则10.0, 0.4, 2.2删除.会将它们乘以十,结果为100, 04, 22(使用旧的测试命令[,前导0s 对于整数比较无关紧要)。当然,您必须相应地乘以边界。

或者,您可以使用bc,它可以处理任意精度的浮点数。bc读取stdin,因此您可以例如回显表达式并将其传输到管道,bc如下所示:

echo "$x>=0.1 && $x<=5.5" | bc

1如果表达式为,则输出为true0否则为 。阅读手册(男人 bc) 来了解更多语法。

要将其合并到您的脚本中,您可以使用如下命令替换:

if [ $(echo "$x>=0.1 && $x<=5.5" | bc) -eq 1 ] ; then cat="good";

请注意,我们仍然需要检查bc命令的输出是否为1,因为[ 0 ]也会计算为true

最后,您的示例使用bc

x=6.5 #(example)
y=-7.5 #(example)
if [ $(echo "$x>=0.1 && $x<=5.5 && $y>=-5.9 && $y<=-0.1" | bc) -eq 1 ] ; then cat="good";
elif [ $(echo "$x>=5.5 && $x<=10.5 && $y>=-10.9 && $y<=-5.9" | bc) -eq 1 ]; then cat="bad";
fi
echo "$cat"

由于括号内难以阅读的字符串更容易出错,因此您可以使用 Bash 函数和变量,如以下示例所示。如果您想添加elif具有不同范围的附加子句,这可能会很有用。(感谢温德雷亚以获得有用的提示)

x=6.5 #(example)
y=-6.5 #(example)

boundsGood="0.1 5.5 -5.9 -0.1"
boundsBad="5.5 10.5 -10.9 -5.9"

# Paramaters in following order: x, y, xmin, xmax, ymin, ymax; bounds are inclusive.
function in_bounds {
    local x=$1
    local y=$2
    local x_min=$3
    local x_max=$4
    local y_min=$5
    local y_max=$6
    [ $(echo "$x >= $x_min && $x <= $x_max && $y >= $y_min && $y <= $y_max" | bc) -eq 1 ]
}

if in_bounds $x $y $boundsGood ; then cat="good";
elif in_bounds $x $y $boundsBad ; then cat="bad";
fi
echo "$cat"

in_bounds该函数的替代版本printf(感谢钢铁司机):

# Paramaters in following order: x, y, xmin, xmax, ymin, ymax; bounds are inclusive.
function in_bounds {
    [ $(printf "x = %f; y = %f; xmin = %f; xmax = %f; ymin = %f; ymax = %f; x >= xmin && x <= xmax && y >= ymin && y <= ymax\n" "$1" "$2" "$3" "$4" "$5" "$6" | bc) -eq 1 ]
}

答案2

如果绝对有必要保留在 shell 脚本中 - 将变量添加到嵌入脚本以将和值awk传递到 awk 的环境中并使用它们来访问它们;并让它完成打印所需字符串的工作(或将整个脚本包装进去以保存输出)。xyENVIRON["variable_name"]$(...)

如果没有必要,就省略 shell 脚本部分,只需让 awk 处理一切。

#!/bin/sh

x=3.5
y=-2.5
x="$x" y="$y" awk 'BEGIN{ 
        print ENVIRON["x"],ENVIRON["y"];
        if ((ENVIRON["x"] >= 0.1) && (ENVIRON["x"] <= 5.5) \
           && (ENVIRON["y"] >= -5.9) &&  (ENVIRON["y"] <= -0.1)){
              print "good";
        }
        else if ((ENVIRON["x"] >= 5.5) && (ENVIRON["x"] <= 10.5) \
           && (ENVIRON["y"] >= -10.9) &&  (ENVIRON["y"] <= -5.9)){
             print "bad";
        }

}' # End of awk

相关内容