regex Bash if语句中的正则表达式匹配

dsekswqp  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(102)

我做错了什么?
尝试匹配任何包含空格、空格、空格或数字的字符串。特殊字符也很好,但我认为这需要转义某些字符。

TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#"

if [[ "$TEST" =~ [a-zA-Z0-9\ ] ]]; then BLAH; fi

这显然只测试了上、下、数字和空格。但不管用。

  • 更新 *

我想我应该说得更具体一点。下面是实际的真实的代码行:

if [[ "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi

这就是错误:

./anm.sh: line 265: syntax error in conditional expression
./anm.sh: line 265: syntax error near `&*#]'
./anm.sh: line 265: `  if [[ ! "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; return; fi'
35g0bw71

35g0bw711#

关于bash的[[ ]]构造,有几件重要的事情需要了解。第一个:
[[]]之间的词不进行分词和路径名扩展;执行波浪号扩展、参数和变量扩展、算术扩展、命令替换、进程替换和引号移除。
第二件事:
一个额外的二元运算符,'= 0',是可用的,.操作符右边的字符串被认为是一个扩展的正则表达式,并相应地匹配.模式的任何部分都可以被引用,以强制将其作为字符串进行匹配
因此,=~两侧的$v将被扩展为该变量的值,但结果不会被字拆分或路径名扩展。换句话说,在左边不加引号的变量扩展是完全安全的,但是你需要知道变量扩展将发生在右边。
所以如果你写:[[ $x =~ [$0-9a-zA-Z] ]],右边的正则表达式中的$0将在解释正则表达式之前被展开,这可能会导致正则表达式无法编译(除非$0的展开以一个数字或标点符号结尾,其值小于数字)。如果你引用右边的[[ $x =~ "[$0-9a-zA-Z]" ]],那么右边将被视为普通字符串,而不是正则表达式$0仍然会被扩展)。在这种情况下,您真正需要的是[[ $x =~ [\$0-9a-zA-Z] ]]
类似地,[[]]之间的表达式在解释正则表达式之前被拆分为单词。所以正则表达式中的空格需要转义或加引号。如果你想匹配字母、数字或空格,你可以使用:用途:[[ $x =~ [0-9a-zA-Z\ ] ]]。其他字符同样需要转义,如#,如果不加引号,将开始一个注解。当然,你可以把模式放到一个变量中:

pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...

对于包含大量需要转义或引用以通过bash的lexer的字符的正则表达式,许多人更喜欢这种风格。但要注意:在这种情况下,你 * 不能 * 引用变量扩展:

# This doesn't work:
if [[ $x =~ "$pat" ]]; then ...

最后,我认为你要做的是验证变量只包含有效的字符。执行此检查的最简单方法是确保它不包含无效字符。换句话说,就是这样一个表达式:

valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list
if [[ ! $x =~ [^$valid] ]]; then ...

!否定测试,将其转换为“不匹配”操作符,[^...]正则表达式字符类表示“除...之外的任何字符“。
参数扩展和正则表达式操作符的组合可以使bash正则表达式语法“几乎可读”,但仍然存在一些问题。不是一直都有吗?一个是你不能把]放进$valid,即使$valid被引用,除非在一开始。(这是一个Posix正则表达式规则:如果你想在一个字符类中包含],它需要在开头。-可以放在开头或结尾,所以如果你同时需要]-,你需要以]开头,以-结尾,这会导致正则表达式“我知道我在做什么”表情:[][-]

ygya80vv

ygya80vv2#

如果有人想要一个使用变量的例子...

#!/bin/bash

# Only continue for 'develop' or 'release/*' branches
BRANCH_REGEX="^(develop$|release//*)"

if [[ $BRANCH =~ $BRANCH_REGEX ]];
then
    echo "BRANCH '$BRANCH' matches BRANCH_REGEX '$BRANCH_REGEX'"
else
    echo "BRANCH '$BRANCH' DOES NOT MATCH BRANCH_REGEX '$BRANCH_REGEX'"
fi
s4n0splo

s4n0splo3#

我更喜欢使用[:punct:]。另外,a-zA-Z09-9也可以是[:alnum:]

[[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]]
q5iwbnjs

q5iwbnjs4#

或者你可能会看到这个问题,因为你碰巧像我一样打了一个愚蠢的错字,把=~颠倒成了~=

相关问题