为什么BASH_REMATCH不能用于带引号的正则表达式?

27

代码如下:

#!/bin/bash
if [[ foobarbletch =~ 'foo(bar)bl(.*)' ]]
 then
     echo "The regex matches!"
     echo $BASH_REMATCH
     echo ${BASH_REMATCH[1]}
     echo ${BASH_REMATCH[2]}
 fi

当我尝试运行它时,它没有显示任何东西:

bash-3.2$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
bash-3.2$ /bin/bash test_rematch.bash
bash-3.2$ 

有人对此有什么想法吗?

3个回答

65

在您的bash正则表达式中,您应该删除引号。这就是为什么它不起作用的原因。

如果有空格,我建议使用以下方式:

#!/bin/bash
x='foo bar bletch'
if [[ $x =~ foo[[:space:]](bar)[[:space:]]bl(.*) ]]
then
    echo The regex matches!
    echo $BASH_REMATCH      
    echo ${BASH_REMATCH[1]} 
    echo ${BASH_REMATCH[2]} 
fi

谢谢!但是如果在正则表达式中出现空格而不使用引号,我该怎么办? - Hanfei Sun
1
@Firegun 另外,你也可以用 \ ' '" "(选择你的毒药)来表示一个空格(第一个没显示好,它是反斜杠后跟着一个空格)。 - doubleDown
7
你可以使用引号,只不过不能将其放在正则表达式元字符的周围。例如,以下代码是可行的:[[ foobarbletch =~ 'foo'('bar')'bl'(.*) ]]。因此,你可以引用任何空格,但不能将整个字符串用引号括起来。 - Mark Reed
1
还要记得通过反斜杠转义文字引号。 - meridius

25

您也可以将带引号的正则表达式分配给一个变量:

#!/bin/bash

x='foobarbletch'

foobar_re='foo(bar)bl(.*)'

if [[ $x =~ $foobar_re ]] ; then
    echo The regex matches!
    echo ${BASH_REMATCH[*]}
    echo ${BASH_REMATCH[1]}
    echo ${BASH_REMATCH[2]}
fi

这不仅支持简单的引用,还为正则表达式赋予了一个名称,有助于提高可读性。


14

由于您的调试语句,echo The regex matches!,您应该已经注意到 BASH_REMATCH 没有问题,因为 if 语句的求值结果为 false

在 bash 中,使用 =~ 的正则表达式不加引号。如果右侧字符串带引号,则它会被视为字符串字面量。

如果您想在您的正则表达式中包含空格,则使用适当的字符类,或者转义您所需要的空格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接