2008-10-20 134 views
60

下面的代碼帶引號的bash正則表達式?

number=1 
if [[ $number =~ [0-9] ]] 
then 
    echo matched 
fi 

作品。如果我嘗試在正則表達式使用引號,但是,它會停止:

number=1 
if [[ $number =~ "[0-9]" ]] 
then 
    echo matched 
fi 

我試過"\[0-9\]"了。我錯過了什麼?

有趣的是,bash advanced scripting guide表明這應該工作。

Bash version 3.2.39。

+2

的ABS是相當臭名昭著爲不準確的來源(或上更好的日子,僅僅是誤導)指導;認爲它是shell腳本的W3Schools。考慮bash-hackers.org或wooledge維基作爲備選方案,注意準確性。 – 2016-07-14 21:36:02

回答

100

它被改變了between 3.1 and 3.2。猜猜高級指南需要更新。

這是添加與bash-3.2由於 釋放的bash-3.1的新 特徵的簡短描述。與往常一樣, 手冊頁(doc/bash.1)是要查找完整說明的地方 。

  1. 在猛砸

剪斷

˚F新功能。引用字符串參數爲 [[command's =〜運算符現在強制 字符串匹配,與其他模式匹配運算符一樣。

不幸的是,除非您有洞察力將模式存儲在變量中並直接使用它們而不是正則表達式,否則這會使用腳本打破現有報價。下面的例子。

$ bash --version 
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu) 
Copyright (C) 2007 Free Software Foundation, Inc. 
$ number=2 
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi 
$ if [[ $number =~ [0-9] ]]; then echo match; fi 
match 
$ re="[0-9]" 
$ if [[ $number =~ $re ]]; then echo MATCH; fi 
MATCH 

$ bash --version 
GNU bash, version 3.00.0(1)-release (i586-suse-linux) 
Copyright (C) 2004 Free Software Foundation, Inc. 
$ number=2 
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi 
match 
$ if [[ "$number" =~ [0-9] ]]; then echo match; fi 
match 
+3

這真的很有趣。引用的正則表達式不再有效。帶空格的未加引號的正則表達式不起作用。即使它們包含空格,基於變量的正則表達式也能正常工作。真是一團糟。 – 2016-10-29 22:25:01

17

擊3.2中引入一個兼容性選項compat31其中恢復的bash正則表達式引用行爲回到3.1

沒有compat31:

$ shopt -u compat31 
$ shopt compat31 
compat31  off 
$ set -x 
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi 
+ [[ 9 =~ \[0-9] ]] 
+ echo no match 
no match 

隨着compat31:

$ shopt -s compat31 
+ shopt -s compat31 
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi 
+ [[ 9 =~ [0-9] ]] 
+ echo match 
match 

鏈接到補丁: http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-039

6

GNU bash中,版本4.2.25(1)-release下(x86_64-PC-Linux的GNU)

字符串匹配正則表達式和匹配的一些實例

$ if [[ 234 =~ "[0-9]" ]]; then echo matches; fi # string match 
    $ 

    $ if [[ 234 =~ [0-9] ]]; then echo matches; fi # regex natch 
    matches 


    $ var="[0-9]" 

    $ if [[ 234 =~ $var ]]; then echo matches; fi # regex match 
    matches 


    $ if [[ 234 =~ "$var" ]]; then echo matches; fi # string match after substituting $var as [0-9] 

    $ if [[ 'rss$var919' =~ "$var" ]]; then echo matches; fi # string match after substituting $var as [0-9] 

    $ if [[ 'rss$var919' =~ $var ]]; then echo matches; fi # regex match after substituting $var as [0-9] 
    matches 


    $ if [[ "rss\$var919" =~ "$var" ]]; then echo matches; fi # string match won't work 

    $ if [[ "rss\\$var919" =~ "$var" ]]; then echo matches; fi # string match won't work 


    $ if [[ "rss'$var'""919" =~ "$var" ]]; then echo matches; fi # $var is substituted on LHS & RHS and then string match happens 
    matches 

    $ if [[ 'rss$var919' =~ "\$var" ]]; then echo matches; fi # string match ! 
    matches 



    $ if [[ 'rss$var919' =~ "$var" ]]; then echo matches; fi # string match failed 
    $ 

    $ if [[ 'rss$var919' =~ '$var' ]]; then echo matches; fi # string match 
    matches 



    $ echo $var 
    [0-9] 

    $ 

    $ if [[ abc123def =~ "[0-9]" ]]; then echo matches; fi 

    $ if [[ abc123def =~ [0-9] ]]; then echo matches; fi 
    matches 

    $ if [[ 'rss$var919' =~ '$var' ]]; then echo matches; fi # string match due to single quotes on RHS $var matches $var 
    matches 


    $ if [[ 'rss$var919' =~ $var ]]; then echo matches; fi # Regex match 
    matches 
    $ if [[ 'rss$var' =~ $var ]]; then echo matches; fi # Above e.g. really is regex match and not string match 
    $ 


    $ if [[ 'rss$var919[0-9]' =~ "$var" ]]; then echo matches; fi # string match RHS substituted and then matched 
    matches 

    $ if [[ 'rss$var919' =~ "'$var'" ]]; then echo matches; fi # trying to string match '$var' fails 


    $ if [[ '$var' =~ "'$var'" ]]; then echo matches; fi # string match still fails as single quotes are omitted on RHS 

    $ if [[ \'$var\' =~ "'$var'" ]]; then echo matches; fi # this string match works as single quotes are included now on RHS 
    matches 
3

正如其他答案中所提到的,將正則表達式放在變量中是實現不同版本的兼容性的一般方法。您也可以使用此解決方法來達到同樣的事情,同時保持你的正則表達式條件表達式中:

$ number=1 
$ if [[ $number =~ $(echo "[0-9]") ]]; then echo matched; fi 
matched 
$