我在这里和编码世界相对较新。我目前正在学习 Shell Scripting 课程,但有点卡住了。
我正在尝试做一些额外的功劳,让脚本检查命令行参数,如果没有或只有 1,则提示用户输入缺失的值。
在大多数情况下,除了数字检查部分之外,我已经能够使其大部分工作。我不完全确定我是否正确执行了嵌套的 if 语句,因为它同时显示了“if”回声和“else”回声。
到目前为止我的脚本:
q=y
# Begins loop
until [[ $q == n ]];do
# Checks command line arguments
if [[ $# -lt 2 ]];then
# Asks for second number if only 1 argument.
if [[ $# == 1 ]];then
read -r -p "Please enter your second number: " y
if [[ y =~ [1-9] ]];then
echo "You've chosen $1 as your first number and $y as your second number."
break
else
echo "This is not a valid value, please try again."
fi
# Asks for both numbers if no arguments.
else
read -r -p "Please enter your first number: " x
if [[ x =~ [1-9] ]];then
break
else
echo "This is not a valid value, please try again."
fi
read -r -p "Please enter your second number: " y
if [[ y =~ [1-9] ]];then
break
else
echo "This is not a valid value, please try again."
fi
echo "You've chosen $x as your first number and $y as your second number."
fi
# If both command line arguments are provided, echo's arguments, and sets arguments as x and y values.
else
echo "You've chosen $1 as your first number and $2 as your second number."
x=$1
y=$2
fi
read -r -p "Would you like to try again? (n to exit): " q
done
当我运行它时,我得到了这个输出:
Please enter your first number: 1
This is not a valid value, please try again.
Please enter your second number: 2
This is not a valid value, please try again.
You've chosen 1 as your first number and 2 as your second number.
Please enter your first number:
并且将继续循环而不中断。任何帮助/指导将不胜感激,谢谢。
答案 0 :(得分:3)
在你的表达中:
if [[ x =~ [1-9] ]]; then
您实际上是在将字符串文字“x”与正则表达式进行比较。你想要的是变量:
if [[ $x =~ [1-9] ]]; then
这将首先插入变量,以便将变量的值与正则表达式进行比较。我认为此更改也适用于您代码中的其他一些比较表达式。
但是,正如 glenn jackman 和 user1934428 所评论的,这也将匹配 foo1bar
之类的内容,这可能不是您想要的。要解决此问题,您可以向正则表达式添加开始/结束匹配器。最后,即使输入有前导或尾随空格,您也可能希望进行匹配。一种方法是添加一些 [[:space:]]*
以匹配 [1-9]
周围的零个或多个空格:
if [[ $x =~ ^[[:space:]]*[1-9][[:space:]]*$ ]]; then
所以,分解正则表达式:
^
开始输入[[:space:]]*
零个或多个空格[1-9]
一位数,1-9[[:space:]]*
零个或多个空格$
输入结束我从您的问题中假设您只想匹配单个数字,而不是例如 12
或数字 0
。要匹配这些需要更多的正则表达式调整。
仅仅因为 glen jackman's answer 带领我进行了 bash 手册页冒险? 并且我想尝试一下,这是一个 glob 模式版本(注意 ==
而不是 =~
):
if [[ $x == *([[:space:]])[1-9]*([[:space:]]) ]]; then
这基本上是相同的模式。但值得注意的是,glob 模式似乎是 implicitly anchored to the start/end of the string being matched(它们针对整个字符串进行测试),因此它们不需要 ^
或 $
,而 regular expressions match against substrings by default,因此它们确实需要这些添加来避免 foo1bar
匹配。无论如何,可能比你想知道的要多。
答案 1 :(得分:2)
这是一个替代实现,供您考虑:有任何问题都可以找我
#!/usr/bin/env bash
get_number() {
local n
while true; do
read -rp "Enter a number between 1 and 9: " n
if [[ $n == [1-9] ]]; then
echo "$n"
return
fi
done
}
case $# in
0) first=$(get_number)
second=$(get_number)
;;
1) first=$1
second=$(get_number)
;;
*) first=$1
second=$2
;;
esac
# or, more compact but harder to grok
[[ -z ${first:=$1} ]] && first=$(get_number)
[[ -z ${second:=$2} ]] && second=$(get_number)
echo "You've chosen $first as your first number and $second as your second number."
这使用:
case
变量的 $#
语句==
中的 [[...]]
运算符进行输入验证——此运算符是一个模式匹配运算符,而不是字符串相等(除非右侧操作数被引用)< /li>
请注意,[[ $x =~ [1-9] ]]
表示:“$x 包含 1 到 9 范围内的一个字符”——它不表示变量 是 一个数字。如果 x=foo1bar
,则正则表达式测试通过。