Скажем, у меня есть координата (x, y), я хочу сделать две категории: хороший или плохой.
Я понятия не имею, как выразить его словами или ключевые слова, таким образом, я создал пример того, что я хочу.
Я создал сценарий удара как это:
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
. С различными границами это должно дать a bad
результат.
Я выполнил его, и это дает результат как ожидаемое целое выражение.
Когда я пытаюсь заменить оператор -ge
(или -le
) с оператором >
(или <
), или попытка добавить квадратную скобку и что-либо, о чем я мог думать, это дает ту же ошибку, или никакие результаты не даны.
Как я должен приблизиться к этому?
Bash может только сделать целочисленную математику. Если значения имеют постоянное число десятичных разрядов, можно удалить .
(использование sed
или awk
или любая команда Вам нравится), и сравните получающиеся значения. Например, если у них есть точно один десятичный разряд как 10.0, 0.4, 2.2
, удаление .
умножит их на десять, приводя к 100, 04, 22
(использование старой тестовой команды [
, продвижение 0
s не имеют значения для целочисленного сравнения). Необходимо будет умножить границы соответственно, конечно.
С другой стороны, можно использовать bc
, который будет работать с числами с плавающей точкой произвольной точности. bc
чтения stdin
, таким образом, можно, например, повторить выражение и передать его по каналу к bc
следующим образом:
echo "$x>=0.1 && $x<=5.5" | bc
Вывод будет 1
если выражение true
, 0
иначе. Прочитайте руководство (человек до н.э), если Вы хотите узнать больше о его синтаксисе.
Для слияния этого в сценарий можно использовать замену команды как это:
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"
Начиная с наличия тех едва читаемых строк в скобках делает это более подверженным ошибкам, можно использовать функции удара и переменные как в следующем примере. Это может быть полезно, если Вы хотите добавить дополнительный elif
пункты с различными диапазонами. (Благодаря wjandrea для полезных подсказок)
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
(благодаря steeldriver):
# 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 ]
}
Если абсолютно необходимо оставаться в сценарии оболочки - добавьте переменные во встроенный сценарий awk
, чтобы передать значения x
и y
в среду awk, и используйте ENVIRON["variable_name"]
для доступа к ним; и пусть он выполняет работу по печати необходимых вам строк (или заключает весь сценарий в $(...)
, чтобы сохранить вывод).
Если в этом нет необходимости, покончите с частью сценария оболочки и просто оставьте 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