正则表达式验证在bash中不起作用

时间:2014-10-05 12:30:44

标签: regex bash

我想使用以下正则表达式来验证项目版本号:

(?!\.)(\d+(\.\d+)+)([-.][A-Z]+)?(?![\d.])$

DEMO

有效输入:

  • 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

我做错了什么?

2 个答案:

答案 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]+)?

这应该有效。