我有这个片段: 其背后的逻辑是,我希望用户输入 -s 后跟一个单词(例如 -sdog)。然而,这不起作用。
read -rp 'choose: ' choice
case $choice in
-a) echo you chose a;;
-s [a-z]+) echo you chose the word ${choice#"-s "};;
esac
非常感谢!!!
答案1
如果您想使用 读取两个单词read
,则使用两个变量:
read -r -p 'Enter "-a" or "-s <word>": ' opt word
case $opt in
-a)
echo 'You picked "-a"'
;;
-s)
printf 'You picked "-s" with the word "%s"\n' "$word"
;;
*)
echo 'You picked neither "-a" nor "-s <word>"'
esac
您的代码不起作用的原因是您使用扩展正则表达式作为模式 ( -s [a-z]+
)。该语句使用的模式case
是文件名通配模式。它们相似但不相同。通配模式不允许使用与正则表达式模式使用的相同类型的“重复修饰符”(+
)。
使用通配模式,您可以使用'-s '[a-z]*
,即“字符串-s
后跟一个小写字母,然后某物^-s [a-z].*
"(与正则表达式相同)。
答案2
您需要转义空格字符(例如答案你之前的问题)。
Bash 将 解释+
为字面意思+
,而不是“一次或多次出现”。 Bash 的模式匹配运算符与正则表达式不同。要匹配一个或多个匹配项,您可以启用“扩展通配符” extglob
shell 选项并使用该+(...)
模式。
为了确保范围表达式[a-z]
仅匹配小写字母(这可能取决于您的区域设置LC_COLLATE
或LC_ALL
设置),您还可以启用globasciiranges
shell 选项。
shopt -s extglob
shopt -s globasciiranges
read -rp 'choose: ' choice
case $choice in
-a)
echo "you chose a"
;;
-s\ +([a-z]))
echo "you chose the word \"${choice#-s }\""
;;
*) echo "unknown choice \"$choice\""
esac
有关的:
- 模式匹配(Bash 参考手册)
答案3
…)
case 语句中不能有(不带引号的)空格。
因此,您需要引用它:\
," "
或' '
:
此外,case 语句的匹配是通过模式而不是正则表达式完成的。+
里面没有模式匹配,只有*
,但这并不意味着重复最后一个元素,而只是“任意计数中的任意字符”。我假设您的[a-z]+
目的是匹配仅由小写字母组成的单词。不可能在更简单的模式匹配字符串中编写相同的内容。可以做的是:
read -rp 'choose: ' choice
case $choice in
-a) echo "you chose a";;
-s\ *[^a-z]*) echo "not a valid word selected";;
-s\ *) echo "you chose the word ${choice#"-s "}";;
*) echo "no choice made";;
esac