Regex preguiçoso usando Bash

Regex preguiçoso usando Bash

Estou tentando corresponder apenas o texto contido nas tags HTML usando a função regex integrada do Bash:

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

Mas a partida continua capturando foo</span>.

A internet está tão cheia de exemplos de sed e grep que não encontrei muita documentação sobre o regex do próprio Bash.

Responder1

Há uma razão pela qual a Internet está repleta de abordagens alternativas. Eu realmente não consigo pensar em nenhuma situação em que você estariaforçadousar o bash para isso. Por que não usar uma das ferramentas projetadas para o trabalho?

De qualquer forma, até onde eu sei não há como fazer partidas não gananciosas usando o =~operador. Isso ocorre porque ele não usa o mecanismo regex interno do bash, mas o mecanismo C do seu sistema, conforme definido em man 3 regex. Isso é explicado em 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)).  

Você pode, no entanto, fazer mais ou menos o que quiser (tendo em mente que isso é realmentenãouma boa maneira de analisar arquivos HTML) com uma regex ligeiramente diferente:

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

O acima retornará fooconforme o esperado.

Responder2

Não sei se as expressões regulares do bash correspondem a uma correspondência não gananciosa como Perl, então use um mecanismo regex Perl:

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

informação relacionada