Regex com Lrexlib

LUA
Enviado por Eclesiastes em Seg, 19/02/2007 - 04:28.LUA

Olá pessoal, como não poderia deixar de ser, demostrarei como utilizar expressões regulares em Lua 5.1 utilizando a biblioteca Lrexlib que provê suporte a POSIX e PCRE.

Instalação

Super simples! Basta ler o readme.txt e saberás como fazer, sem mistério!

Dica

Vale lembrar que ao usar seqüência de escape você terá que usar escape na barra se utilizar a string delimitada por aspas simples ou dupla. Porém o mesmo não é necessário quando é usado [[ e ]] para delimitar.

Exemplo:

  1. er = [[\w+]]

  1. er = '\\w+'

Flags

Para conhecer as flags que poderão ser utilizadas nas funções listadas abaixo, basta executar o seguinte código:

  1. rex = require('rex_pcre')
  2.  
  3. table.foreach(rex.flags(), print)

Que será listada todas as flags e seus respectivos valores.

Lrexlib Funções

match

rex.match (subj, patt, [init], [cf], [ef], [lo])

Esta função faz uma busca pela primeira ocorrência da combinação da expressão regular em uma string subj, iniciando de init, usandos as flags cf e ef.

Em caso de sucesso, a função retorna todas as substrings capturadas (caso utilize grupos). false quando um sub-pattern não fazer parte da combinação. Se o pattern não contém grupo, é retornada toda a substring.
Em caso de falha, é retornado nil.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. match = rex.match('abc foo def', 'fo+')
  4. print('Casou: ', match)

find

rex.find (subj, patt, [init], [cf], [ef], [lo])

Os argumento são os mesmos da função acima, a diferença está no retorno, está retorna a posição inicial e final da substring que fora casada, e para retorna a substring casada, você terá que colocar dentro de um grupo.
Em caso de falha, retornará nil.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. posi, posf, match = rex.find('abc foo def', '(fo+)')
  4. print('Pos. inicial: ', posi)
  5. print('Pos. final: ', posf)
  6. print('Casou: ', match)

gmatch

rex.gmatch (subj, patt, [cf], [ef], [lo])

Esta função retorna um iterator para que seja visualizada todas as combinações que foram feitas em toda a string.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. matches = rex.gmatch('a 11 b 12 c 13', [[\d+]])
  4.  
  5. for str in matches do
  6.     print(str)
  7. end

gsub

rex.gsub (subj, patt, repl, [n], [cf], [ef], [lo])

Esta função procura por todas as combinações da expressão na string subj e substitue o que é encontrado de acordo com o que é especificado no parametro repl.
Sendo que este argumento repl pode ser de 3 tipos. String, function ou table.

Se for uma string, você poderá usar %N para indicar o que foi capturado no N grupo. Caso o '%' não esteja precedendo um dígito, o mesmo será desconsiderado.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. print(rex.flags().CASELESS)
  4.  
  5. str = 'Foooooooo'
  6.  
  7. -- CASELESS => 1
  8. -- rex.flags()['CASELESS']
  9. -- rex.flags().CASELESS
  10. str = rex.gsub(str, 'O+', 'oo', nil, 1)
  11.  
  12. print(str)

Se for function, o que for combinado será repassado como argumento da função, podendo assim ser obtido na função pela variável arg, ou se preferir, você pode declarar os argumentos da função.

Exemplos:

  1. rex = require('rex_pcre')
  2.  
  3. function mod (...)
  4.     return '-' .. arg[1] .. '-'
  5. end
  6.  
  7. str = rex.gsub('Foo', '.', mod)
  8.  
  9. print(str)

  1. rex = require('rex_pcre')
  2.  
  3. function mod (a, b)
  4.     return '[' .. a .. '|' .. b .. ']'
  5. end
  6.  
  7. str = rex.gsub('foo', '(.)(.)$', mod)
  8.  
  9. print(str)

Se for table, será procurada uma chave na Table com o mesmo valor da string encontrada.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. a = {f = 'h', o = 'm'}
  4.  
  5. str = rex.gsub('foo', '.', a)
  6.  
  7. print(str)

split

rex.split (subj, sep, [cf], [ef], [lo])

Esta função é usada para capturar pedaços da string entre um separador definido por uma expressão regular.

A função retorna um iterator, que retorna uma substring a cada chamada.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. letras = rex.split('a.b,c;d', '[.,;]')
  4.  
  5. for letra in letras do
  6.     print(letra)
  7. end

plainfind

rex.plainfind (subj, patt, [init], [ci])

Uma função similar à find, encontra a primeira ocorrência. Porém ela não trabalha com biblioteca PCRE/POSIX.
A string patt não é uma expressão regular.
init indica de onde irá começar. (aceita valor negativo)
E a flag ci especifica busca case-insensitive.

Em caso de sucesso, é retornado a posição inicial e final da combinação.
E em caso de falha, é retorando nil.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. posi, posf = rex.plainfind('pera uva abacaxi', 'uva')
  4.  
  5. print('Pos. inicial: ', posi)
  6. print('Pos. final: ', posf)

new

rex.new (patt, [cf], [lo])

Esta função compila uma expressão regular para um objeto com representação interna correspondente a biblioteca usada. (PCRE ou POSIX)
O resultado retornado (userdata) então pode ser usado por métodos tfind, exec e dfa_exec. Estes objetos são automáticamente removidos. (Garbage collected)

Conheça os métodos a seguir.

Lrexlib Métodos

tfind

r:tfind (subj, [init], [ef])

Este método procura pela primeira combinação do expressão compilada na string subj, iniciando de init, sobre as flags ef.

Em caso de sucesso, é retornada a posição inicial e final da string combinada.
Substrings capturadas (entre grupos) são retornadas em um terceiro resultado, em uma table. Que contém valor false nas posições que não casarem as subexpressões na combinação.
Usando grupos nomeados, será criada a chave correspondente com tal nome.
Em caso de falha, retornará false.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. er = rex.new([[(?P<nome>\w+) (?P<idade>\d+)]])
  4.  
  5. posi, posf, data = er:tfind('Felipe 18')
  6.  
  7. print('Nome: ', data['nome'])
  8. print('Idade: ', data['idade'])

exec

r:exec (subj, [init], [ef])

Possui a mesma descrição do método acima, o que muda é o retorno. Este retorna os offsets das substrings casadas. E quanto aos grupos nomeados, eles também são retornados.

dfa_exec

r:dfa_exec (subj, [init], [ef], [ovecsize], [wscount])

Este método combina a expressão compilada com dada string subj usando o algoritmo DFA.

Em caso de sucesso, é retornado a posição inicial das combinações obtidas.
Uma table contendo as posições finais das combinações.
E também retorna um valor sobre a chamada pcre_dfa_exec.

Em caso de falha, é retornado nil.

Exemplo:

  1. rex = require('rex_pcre')
  2.  
  3. er = rex.new([[fo+]], 1)
  4.  
  5. posi, data, n = er:dfa_exec('fooooo')
  6.  
  7. table.foreach(data, print)

Enfim, resumi bastante, e espero que os exemplos ajudem a quem estiver precisando. Já que não há no manual.

Referências

Lrexlib 2.1 Reference Manual - http://lrexlib.luaforge.net/manual.html
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4905