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:
Flags
Para conhecer as flags que poderão ser utilizadas nas funções listadas abaixo, basta executar o seguinte código:
rex = require('rex_pcre')
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:
rex = require('rex_pcre')
match = rex.match('abc foo def', 'fo+')
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:
rex = require('rex_pcre')
posi, posf, match = rex.find('abc foo def', '(fo+)')
print('Pos. inicial: ', posi)
print('Pos. final: ', posf)
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:
rex = require('rex_pcre')
matches = rex.gmatch('a 11 b 12 c 13', [[\d+]])
for str in matches do
print(str)
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:
rex = require('rex_pcre')
print(rex.flags().CASELESS)
str = 'Foooooooo'
-- CASELESS => 1
-- rex.flags()['CASELESS']
-- rex.flags().CASELESS
str = rex.gsub(str, 'O+', 'oo', nil, 1)
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:
rex = require('rex_pcre')
function mod (...)
return '-' .. arg[1] .. '-'
end
str = rex.gsub('Foo', '.', mod)
print(str)
rex = require('rex_pcre')
function mod (a, b)
return '[' .. a .. '|' .. b .. ']'
end
str = rex.gsub('foo', '(.)(.)$', mod)
print(str)
Se for table, será procurada uma chave na Table com o mesmo valor da string encontrada.
Exemplo:
rex = require('rex_pcre')
a = {f = 'h', o = 'm'}
str = rex.gsub('foo', '.', a)
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:
rex = require('rex_pcre')
letras = rex.split('a.b,c;d', '[.,;]')
for letra in letras do
print(letra)
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:
rex = require('rex_pcre')
posi, posf = rex.plainfind('pera uva abacaxi', 'uva')
print('Pos. inicial: ', posi)
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:
rex = require('rex_pcre')
er = rex.new([[(?P<nome>\w+) (?P<idade>\d+)]])
posi, posf, data = er:tfind('Felipe 18')
print('Nome: ', data['nome'])
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:
rex = require('rex_pcre')
er = rex.new([[fo+]], 1)
posi, data, n = er:dfa_exec('fooooo')
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