Expresión regular perezosa usando Bash

Expresión regular perezosa usando Bash

Estoy tratando de hacer coincidir solo el texto contenido en las etiquetas HTML usando la función de expresiones regulares incorporada de Bash:

string='<span class="circle"> </span>foo</span></span>'
regex='<span class="circle"> </span>(.+?)</span>'
[[ $string =~ $regex ]]
echo "${BASH_REMATCH[1]}"

Pero el partido sigue capturando foo</span>.

Internet está tan lleno de ejemplos de sed y grep que no he encontrado mucha documentación sobre la propia expresión regular de Bash.

Respuesta1

Hay una razón por la cual Internet está repleto de enfoques alternativos. Realmente no puedo pensar en ninguna situación en la que estaríasforzadousar bash para esto. ¿Por qué no utilizar una de las herramientas diseñadas para el trabajo?

De todos modos, hasta donde yo sé, no hay forma de hacer coincidencias no codiciosas usando el =~operador. Esto se debe a que no utiliza el motor de expresiones regulares interno de bash, sino el motor C de su sistema, tal como se define en man 3 regex. Esto se explica en man bash:

   An additional binary operator, =~, is available, with the  same  prece‐
   dence  as  ==  and !=.  When it is used, the string to the right of the
   operator is considered  an  extended  regular  expression  and  matched
   accordingly  (as  in  regex(3)).  

Sin embargo, puedes hacer más o menos lo que quieras (teniendo en cuenta que esto es realmentenouna buena forma de analizar archivos HTML) con una expresión regular ligeramente diferente:

string='<span class="circle"> </span>foo</span></span>'
regex='<span class="circle"> </span>([^<]+)</span>'
[[ $string =~ $regex ]]; 
echo "${BASH_REMATCH[1]}"

Lo anterior volverá foocomo se esperaba.

Respuesta2

No sé si las expresiones regulares de bash coinciden con coincidencias no codiciosas como Perl, así que use un motor de expresiones regulares de Perl:

$ grep -oP '<span class="circle"> </span>\K.+?(?=</span>)' <<<"$string"
foo

información relacionada