2008-10-20 7 views
60

El siguiente códigobash regex con comillas?

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

obras. Si trato de usar comillas en la expresión regular, sin embargo, se detiene:

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

me trataron "\[0-9\]", también. ¿Qué me estoy perdiendo?

Curiosamente, bash advanced scripting guide sugiere que esto debería funcionar.

Bash versión 3.2.39.

+2

El ABS es bastante notoria como fuente para inexacta (o, en tiempos mejores, simplemente engañosa) guía; considérelo el W3Schools de las secuencias de comandos shell. Considere los wikis de bash-hackers.org o wooledge como alternativas que se mantienen con la vista puesta en la precisión. –

Respuesta

100

Fue cambiado between 3.1 and 3.2. Supongo que la guía avanzada necesita una actualización.

Ésta es una descripción concisa de las nuevas características añadidas a bash3.2 desde el lanzamiento de bash-3.1. Como siempre, la página del manual (doc/bash.1) es el lugar para buscar descripciones completas.

  1. Nuevas características de Bash

tijeretazo

f. Citando el argumento de cadena al [[command's = ~ operador ahora fuerza cadena coincidente, como con los otros operadores de coincidencia de patrones.

Lamentablemente, esto va a romper la cita existente usando scripts a menos que tenga la idea de almacenar patrones en variables y usarlos en lugar de las expresiones regulares directamente. Ejemplo a continuación.

$ 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

Esto es muy divertido. Las expresiones regulares citadas ya no funcionan. Las expresiones regulares sin cita con espacios no funcionan. Las expresiones regulares basadas en variables funcionan incluso si incluyen espacios. Que desastre. –

17

Bash 3.2 introdujo una opción compat31 compatibilidad que revierte fiesta regular de comportamiento citando la expresión de nuevo a 3,1

Sin 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 

Con 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 

Enlace al parche: http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-039

6

GNU bash, versión 4.2.25 (1) -release (x86_64-pc-linux-gnu)

Algunos ejemplos de combinación de cadena y combinar expresiones regulares

$ 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

Como se menciona en otras respuestas, poner la expresión regular en una variable es una forma general de lograr compatibilidad con diferentes versiones de .También puede utilizar esta solución para lograr lo mismo, manteniendo su expresión regular dentro de la expresión condicional:

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