Bash = ~ regex y https://regex101.com/

12

Usando https://regex101.com/ Construí una expresión regular para devolver la primera aparición de una dirección IP en una cadena.

RegExp:

(?:\d{1,3}\.)+(?:\d{1,3})

RegExp incluyendo delimitadores:

/(?:\d{1,3}\.)+(?:\d{1,3})/

Con la siguiente cadena de prueba:

eu-west                       140.243.64.99 

Devuelve una coincidencia completa de:

140.243.64.99

No importa lo que intente con los anclajes, etc., el siguiente script bash no funcionará con la expresión regular generada.

temp="eu-west                       140.243.64.99            "
regexp="(?:\d{1,3}\.)+(?:\d{1,3})"
if [[ $temp =~ $regexp ]]; then
  echo "found a match"
else
  echo "No IP address returned"
fi
rjm61
fuente
3
Eso me parece una expresión regular de Perl. Bash no es compatible con eso.
Kusalananda
1
El =~operador se trata aquí en el manual donde está escrito bash usa "expresiones regulares extendidas". Las expresiones regulares extendidas se describen en la regex(7)página del manual y se resumen brevemente aquí .
Glenn Jackman

Respuestas:

15

\des una forma no estándar de decir "cualquier dígito". Creo que proviene de Perl, y muchos otros lenguajes y utilidades también admiten RE compatibles con Perl (PCRE). (y, por ejemplo, GNU grep 2.27 en Debian stretch admite \wcaracteres similares para palabras incluso en modo normal).

Sin \dembargo, Bash no es compatible , por lo que debe usar explícitamente [0-9]o [[:digit:]]. Lo mismo para el grupo que no captura (?:..), use solo en su (..)lugar.

Esto debería imprimir match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match
ilkkachu
fuente
2
¿Su GNU grepsoporta \dsin -P?
Stéphane Chazelas
@ StéphaneChazelas, whoops, por supuesto que no. Es compatible \wy \b, lo que aprendí de Perl, me confundí.
ilkkachu
no es realmente justo decir \do PCRE son "no estándar". Son bastante estándar, solo un estándar diferente de las expresiones regulares originales y las expresiones regulares extendidas.
Daniel Farrell
1
@DanielFarrell, el estándar en este caso es lo que POSIX especifica , y no lo sabe \d. Aunque tiene razón en que PCRE son bastante estándar, o en el menos bien definido. El problema molesto es que GNU grep (o glibc) soporta algunas PCRE-como los átomos, al menos \wy \sal interpretar ERE, y en ese contexto que mucho son no estándar. Mi fraseo bien puede provenir en parte de eso, y la mala recopilación que también \dfue respaldada por GNU.
ilkkachu
4

(:...)y \dson operadores de expresión regular perl o PCRE (como en GNU grep -P).

bashsolo admite expresiones regulares extendidas como en grep -Eexcepto que para expresiones regulares pasadas literalmente en [[ text =~ regexp-here ]]lugar de como resultado de una expansión sin comillas (como en [[ text =~ $var ]]o [[ test =~ $(printf '%s\n' 'regexp-here') ]]), se limita al conjunto de características de expresión regular extendida POSIX.

Entonces, incluso en los sistemas donde grep -E '\d'funcionaría (los ERE de GNU ya han importado algunas extensiones de expresiones regulares perl, por \slo que las futuras versiones también podrían tenerlo \d), tendría que usar:

regexp='\d'
[[ $text =~ $regexp ]]

en bashpara que funcione ( [[ $text =~ \d ]]no).

Para un shell que admita PCRE, puede utilizar zshen su lugar:

set -o rematchpcre
[[ $text =~ '(?:\d{1,3}\.)+(?:\d{1,3})' ]]

ksh93 también admite su propia implementación de expresiones regulares similares a perl (no totalmente compatibles) como parte de su coincidencia de patrones. Allí, usarías:

regexp='~(P)(?:\d{1,3}\.)+(?:\d{1,3})'
[[ $text = $regexp ]]

(tenga =en cuenta el en lugar de =~. Querrá usar variables temporales ya que es muy defectuoso cuando no lo hace)

Stéphane Chazelas
fuente
1

El sitio regex101.com usa PCRE (mira en la esquina superior izquierda) como predeterminado, y carece de soporte para la sintaxis de expresiones regulares "Extendida". Es "Expresiones regulares compatibles con Perl", que provienen (como es razonable esperar) de Perl.

PCRE es compatible con algunas herramientas (como grep -P) en algunas condiciones, pero el soporte de bash regex dentro del [[…]]idioma es solo para expresiones regulares extendidas (like grep -E).

En la expresión regular extendida, el (?…)paréntesis de no captura no existe y también falta el \ d. Necesita usar simple (…)y [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Isaac
fuente