英文:
How to check if a number is outside a dynamic range in bash?
问题
我有一个披萨生成器的代码。它允许用户选择披萨的大小和来自侧边文件的配料列表。
我正在尝试验证用户的输入,以便输入一个介于1和来自侧边文件的配料数量之间的数字。
我从文件中获取行数并将其存储在一个变量中,使用以下命令:
numtop=$( cat Toppings | wc -l );
然后,我读取用户的输入并使用if语句进行检查:
read topp
if [[ "$topp" < 1 || "$topp" > "$numtop" ]]; then
echo "请输入1到" $numtop
else
echo "好选择"
fi
但它只允许我输入1或来自$numtop变量的数字。我不明白为什么这不起作用。
英文:
I have a pizza builder code. It gives the user to chose a pizza size and a list of toppings from a side file.
I'm trying to validate users input so it can enter a number between 1 and the amount of toppings from the side file.
I'm getting the number of rows from the file and set it to a variable using wc
numtop=$( cat Toppings | wc -l );
After that I read the users input and run a check using if
read topp
if [[ "$topp" < 1 || "$topp" > "$numtop" ]]; then
echo "Enter from 1 to " $numtop
else
echo "Good choice"
fi
But it allows me to enter only 1 or the number from my $numtop variable. I can't understand why this doesn't work.
答案1
得分: 1
你需要在算术表达式中使用 (( ))
,类似于:
#!/usr/bin/env bash
numtop="$(wc -l < Toppings)"
while read -rp "输入 1 到 $numtop 之间的数字:" topp; do
if (( topp < 1 || topp > numtop )); then
echo "请输入 1 到 $numtop 之间的数字"
else
echo "选择有效"
break
fi
done
编辑:根据 @jhnc
的建议,如果输入类似于:a[$(date>/dev/tty)],1
(第一个答案可能会出错),首先检查输入的值是否严格为数字。
#!/usr/bin/env bash
##: 还要测试 Toppings 是否为空文件
##: 或者只需测试 $numtop 的值。
numtop="$(wc -l < Toppings)"
while printf '输入 1 到 %s 之间的数字:' "$numtop"; do
read -r topp
case $topp in
('')
printf '输入为空\n' >&2
;;
(*[!0123456789]*)
printf '%s 中有非数字字符\n' "$topp" >&2
;;
(*)
if (( topp < 1 || topp > numtop )); then
printf '你输入了 %s\n' "$topp" >&2
else
printf '你输入了 %s,选择有效!\n' "$topp" &&
break
fi
;;
esac
done
-
在
[[ ... ]]
中使用的<
和>
不是用于 bash 中的算术表达式,参见help test
。它们用于测试字符串的字典顺序。 -
请参阅在线 bash 手册中的 Conditional Constructs,查找
[[ expression ]]
,其中指出:“在与 [[ 一起使用时,‘<’ 和 ‘>’ 运算符使用当前区域设置进行字典排序。” -
请参阅 How can I tell whether a variable contains a valid number?。
-
numtop=$( cat Toppings | wc -l );
是 UUOC 的一种形式。
英文:
You need to use the (( ))
for arithmetic expression, something like:
#!/usr/bin/env bash
numtop="$(wc -l < Toppings)"
while read -rp "Enter from 1 to $numtop " topp; do
if (( topp < 1 || topp > numtop )); then
echo "Enter from 1 to $numtop"
else
echo "Good choice"
break
fi
done
EDIT: as per @jhnc
, Given the input is something like: a[$(date>/dev/tty)],1
(the first answer breaks badly) check the value of input first if it is strictly numeric.
#!/usr/bin/env bash
##: Test also if Toppings is empty if it is a file
##: or just test the value of $numtop.
numtop="$(wc -l < Toppings)"
while printf 'Enter from 1 to %s ' "$numtop"; do
read -r topp
case $topp in
('')
printf 'input is empty\n' >&2
;;
(*[!0123456789]*)
printf '%s has a non-digit somewhere in it\n' "$topp" >&2
;;
(*)
if (( topp < 1 || topp > numtop )); then
printf 'You entered %s\n' "$topp" >&2
else
printf 'You entered %s Good choice!\n' "$topp" &&
break
fi
;;
esac
done
-
The
<
and>
when used in[[ ... ]]
is not for arithmetic expression in bash, seehelp test
. It is used for testing strings lexicographical -
See Conditional Constructs from the online bash manual and look for the
[[ expression ]]
, which states:When used with [[, the ‘<’ and ‘>’ operators sort lexicographically using the current locale.
-
See How can I tell whether a variable contains a valid number?.
-
numtop=$( cat Toppings | wc -l );
is a form of UUOC
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论