我想匹配case
语句中的版本号。版本号可能如下所示
1.12.0.32
1.12.0.32.1
2.10.0.30.1.2
并存储在 shell 变量中:version
.
正如我在互联网上搜索的那样,在 - 语句中匹配正则表达式并不困难case
。但是,有没有人有想法或可以帮助如何在 - 语句中完成它case
?
我尝试了以下方法,但没有成功:
case "$version" in
"([0-9]+\.*)+")
echo "Correct"
;;
*)
echo "Not Correct"
;;
esac
答案1
case
仅支持 shell 模式,不支持正则表达式。但 Bash 支持使用不同语法的开箱即用的正则表达式。
如果您的意思是“由点分隔的任意数量的十进制数字”,并且例如没有尾随字母或标签,那么该模式^[0-9]+(\.[0-9]+)*$
可能是合适的。([0-9]+\.*)+
还可以匹配带有连续点或尾随点的字符串,例如1.2..3.
.所以:
#!/bin/bash
re='^[0-9]+(\.[0-9]+)*$';
if [[ $version =~ $re ]]; then
echo "'$version' matches the pattern"
else
echo "'$version' doesn't match"
fi
正则表达式表示查找任意数量的十进制数字 ( [0-9]+
),后跟(·)*
由文字点 ( \.
) 和任意数量的十进制数字( ) 组成的任意数量的组 ( [0-9]+
)。^
并将$
模式锁定到字符串的开头和结尾,否则匹配的子字符串就足以进行匹配。
这将允许版本字符串没有任何点,例如123
.如果您想要至少需要两个数字和点,请使用^[0-9]+(\.[0-9]+)+$
(将最后一个更改*
为+
)。
请注意,根据区域设置,[0-9]
匹配的内容可能会有点令人惊讶,它可能包含一些更奇怪的 Unicode 数字。用 拼写出允许的字符[0123456789]
会更严格,但写起来更尴尬且容易出错。
答案2
case
匹配 shell 模式,而不是正则表达式。因此,^[0-9]+(\.[0-9]+)*$
您可以使用以下命令来代替正则表达式:
case $version in
'' | *[!0123456789.]* | .* | *. | *..* ) echo invalid;;
* ) echo fine;;
esac
即“反转”匹配意义,使用标准 shell 模式来检测无效情况。
请注意,extglob
bash 选项适用于case
语句中的匹配。因此,如果您使用 进行了设置shopt -s extglob
,那么那些扩展模式(如+()
、*()
等)将获得其特殊含义,并且您可以通过使用(shell 模式已经“锚定”到开头和结尾)进行更像正则表达式的正匹配+([0123456789])*(.+([0123456789]))
。
答案3
如果不是必须的,case
并且您允许使用像 之类的外部工具grep
,则可以使用if
可能提供更大灵活性的语句:
if grep -q -E '^[0-9]+(\.[0-9]+)*$' <<< "$version"
then
printf "%s is a valid version\n" "$version"
else
printf "%s is NOT a valid version\n" "$version"
fi
这将接受包含以下内容的版本字符串
- 至少一个字段由一位或多位连续数字 (
[0-9]+
) 组成,后跟 - 零个或多个以分隔符
.
(转义为\.
正则表达式中的简单意思.
是“任何字符”),后跟一个或多个连续数字(再次[0-9]+
)。
^
通过将匹配锚定到字符串的开始 ( ) 和结束 ( )来确保匹配的详尽性$
,因此单纯的子字符串匹配不会触发结果。