我想使用以下正则表达式来验证项目版本号:
(?!\.)(\d+(\.\d+)+)([-.][A-Z]+)?(?![\d.])$
有效输入:
1.0.0-SNAPSHOT
1.0.0.RC
1.0.0
我正在尝试使用如下脚本:
#!/bin/bash
r=true;
p="(?!\.)(\d+(\.\d+)+)([-.][A-Z]+)?(?![\d.])$"
while [ $r == true ]; do
echo "get_v: "
read v;
if [[ $v =~ $p ]]; then
echo "ok";
r=false
else
echo "nok"
fi
done
但它也通过使用有效输入返回 NOK 。
我做错了什么?
答案 0 :(得分:4)
Bash不支持pcre
- perl正则表达式。它支持extended regular expr - ERE。
您可以使用grep -P
检查字符串,如:
while read -r ver
do
res=$(grep -oP '(?!\.)(\d+(\.\d+)+)([-.][A-Z]+)?(?![\d.])$' <<<"$ver")
echo "ver:$ver status:$? result:=$res="
done <<EOF | column -t
1
1-release
1.2
1.2-dev1
1.0.0-release
1.0.0.3
Q
x-release
1.x
z.2
1.x-dev1
1.x.0-dev3
.1.0-dev3
v1
v1.3-SNAPSHOT
EOF
然而,重新检查你的正则表达式,因为上面打印:
ver:1 status:1 result:==
ver:1-release status:1 result:==
ver:1.2 status:0 result:=1.2=
ver:1.2-dev1 status:1 result:==
ver:1.0.0-release status:1 result:==
ver:1.0.0.3 status:0 result:=1.0.0.3=
ver:Q status:1 result:==
ver:x-release status:1 result:==
ver:1.x status:1 result:==
ver:z.2 status:1 result:==
ver:1.x-dev1 status:1 result:==
ver:1.x.0-dev3 status:1 result:==
ver:.1.0-dev3 status:1 result:==
ver:v1 status:1 result:==
ver:v1.3-SNAPSHOT status:0 result:=1.3-SNAPSHOT=
我会用
r='((?<=\A)|(?<=\s))v?\d+(\.\d+)*(-\w+)?(?=(\s|\z))'
e.g:
r='((?<=\A)|(?<=\s))v?\d+(\.\d+)*(-\w+)?(?=(\s|\z))'
while IFS= read -r ver
do
res=$(grep -oP "$r" <<<"$ver")
printf "ver:%-15.15s status:%s result:=%s=\n" "$ver" $? "$res"
done <<EOF
1
1-release
1.2
1.2-dev1
1.0.0-release
1.0.0.3
Q
x-release
1.x
z.2
1.x-dev1
1.x.0-dev3
.1.0-dev3
v1
v1.3-SNAPSHOT
EOF
打印:
ver:1 status:0 result:=1=
ver: 1-release status:0 result:=1-release=
ver: 1.2 status:0 result:=1.2=
ver:1.2-dev1 status:0 result:=1.2-dev1=
ver:1.0.0-release status:0 result:=1.0.0-release=
ver:1.0.0.3 status:0 result:=1.0.0.3=
ver:Q status:1 result:==
ver:x-release status:1 result:==
ver:1.x status:1 result:==
ver:z.2 status:1 result:==
ver:1.x-dev1 status:1 result:==
ver:1.x.0-dev3 status:1 result:==
ver:.1.0-dev3 status:1 result:==
ver:v1 status:0 result:=v1=
ver:v1.3-SNAPSHOT status:0 result:=v1.3-SNAPSHOT=
如果您不希望允许v1.1
- 例如v
在开头删除正则表达式中的v?
。
如果您想要更严格的正则表达式,请使用
r='((?<=\A)|(?<=\s))\d+(\.\d+){1,2}(-[A-Z]+)?(?=(\s|\z))'
只允许2个或3个数字,只允许-
之后的大写。
最后,如果你想要纯粹的bash - 使用ERE就像下一个:
r='^[0-9]+(\.[0-9]+)+(-[A-Z]+)?$'
while read -r ver
do
[[ $ver =~ $r ]] && echo "$ver: ok" || echo "$ver: no"
done <<EOF | column -t
1
1-RELEASE
1.2
1.2-DEV
1.2-DEV2
1.0.0-RELEASE
1.0.0
1.0.0.3
Q
x-RELEASE
1.x
z.2
1.x-DEV
1.x.0-DEV
.1.0-DEV
v1
v1.3-SNAPSHOT
EOF
打印
1: no
1-RELEASE: no
1.2: ok
1.2-DEV: ok
1.2-DEV2: no
1.0.0-RELEASE: ok
1.0.0: ok
1.0.0.3: ok
Q: no
x-RELEASE: no
1.x: no
z.2: no
1.x-DEV: no
1.x.0-DEV: no
.1.0-DEV: no
v1: no
v1.3-SNAPSHOT: no
答案 1 :(得分:1)
你的正则表达式使用了环视,而bash并不支持。但是,一旦你的正则表达式出现了一些“问题”,你就不需要环顾四周了。固定的。
可以删除环视,而无需更改匹配项。
领先的前瞻不可能失败:
(?!\.)(\d+...
因为正则表达式以数字开头,所以不必断言它不是一个点。
前瞻性的前瞻也不可能失败:
(?![\d.])$
输入结束不能是数字。
您还有不必要的括号。删除所有不必要的部分后,我们得到:
\d+(\.\d+)+([-.][A-Z]+)?
但bash不支持\d
,因此请尝试使用[0-9]
代替\d
:
[0-9]+(\.[0-9]+)+([-.][A-Z]+)?
这应该有效。