&Anders.Lund; &Anders.Lund.mail; JoséPires
jncp@netcabo.pt
Tradução
Expressões Regulares Este Apêndice contém uma breve, mas abrangente e suficiente, introdução ao mundo das expressões regulares. Ela documenta as expressões regulares na forma que está disponível no &kate;, a qual não é compatível com as expressões regulares do Perl, nem com as do grep, por exemplo. Introdução As Expressões Regulares oferecem-nos uma forma de descrever alguns conteúdos possíveis de uma sequência de texto, a qual pode ser compreendida de certa forma por algum 'software', de modo a que este possa investigar se um texto corresponde, e também no caso das aplicações avançadas, com a possibilidade de guardar pedaços do texto correspondente. Um exemplo: Imagine que deseja procurar num texto por parágrafos que comecem quer pelos nomes Henrique ou Pedro, seguidos de alguma forma do verbo dizer. Com uma pesquisa normal, iria começar a procurar pelo primeiro nome, Henrique, sendo talvez seguido de di, como o seguinte: Henrique di e, enquanto procura por ocorrências, iria ignorar os que não se encontram no início de um parágrafo, assim como os que têm uma palavra que começa por di que não é diz, disse ou algo do género. Claro, e ainda ter que repetir isto com o próximo nome... Com as Expressões Regulares, essa tarefa pode ser acompanhada com uma única pesquisa e com um maior grau de precisão. Para conseguir isto, as Expressões Regulares definem regras para exprimir com detalhe uma generalização de uma sequência de texto com a qual corresponder. No nosso exemplo, o qual podemos exprimir literalmente da seguinte forma: Uma linha que começa por Henrique ou Pedro (possivelmente a seguir a 4 espaços ou tabulações) seguida de um espaço em branco e da sequência di, sendo esta seguida de z ou sse pode ser expressa com a seguinte expressão regular: ^[ \t]{0,4}(Henrique|Pedro) di(z|sse) O exemplo anterior demonstra todos os quatro maiores conceitos das expressões regulares modernas, nomeadamente: Padrões Asserções Quantificadores Referências anteriores O acento circunflexo (^) no início da expressão é uma asserção ou verificação que é verdadeira só se o texto correspondente está no início da linha. As sequências [ \t] e (Henrique|Pedro) di(z|se) são padrões. O primeiro é uma classe de caracteres que corresponde quer a um espaço em branco quer a uma tabulação (horizontal); o outro padrão contém, em primeiro lugar, um sub-padrão que corresponde quer a Henrique quer a Pedro, pelo que se segue o texto exacto di e, finalmente, existe um sub-padrão que corresponde a z ou a sse A sequência {0,4} é um quantificador que diz qualquer número de vezes entre 0 e 4 da sequência anterior. Como o 'software' de expressões regulares suporta o conceito de referências anteriores, ele guarda a parte inteira correspondente ao texto, bem como aos sub-padrões entre parêntesis; se for dado um meio de aceder a essas referências, pode-se aceder a toda a correspondência (ao procurar num documento de texto num editor com uma expressão regular, esta é normalmente marcada como seleccionada), apenas ao nome encontrado, ou à última parte do verbo. Tudo em conjunto, a expressão irá corresponder onde nós queiramos que o faça, e só aí. As secções seguintes irão descrever em detalhe como construir e usar os padrões, as classes de caracteres, as verificações, os quantificadores e as referências anteriores; a secção final irá dar alguns exemplos úteis. Padrões Os padrões consistem em cadeias de caracteres literais e em classes de caracteres. Os padrões podem conter sub-padrões, que são padrões entre parêntesis. Caracteres de escape Tanto nos padrões como nas classes de caracteres, alguns caracteres têm um significado especial. Para corresponder literalmente com algum desses caracteres, estes têm de ser marcados ou escapados, para permitir ao 'software' de expressões regulares perceber que deve interpretar esses caracteres no seu sentido literal. Isto é feito, antecedendo o carácter com uma barra invertida (\). O 'software' de expressões regulares irá ignorar silenciosamente uma barra para um carácter que não tenha um significado especial no contexto; por isso, se escapar, por exemplo, um j (\j), não há problema. Se tiver dúvidas se um carácter poderá ter algum significado especial, podê-lo-á então escapar em segurança. A marcação inclui o próprio carácter de barra; por isso, para escapar uma barra, deveria escrever \\. Classes de Caracteres e abreviaturas Uma classe de caracteres é uma expressão que corresponde a um carácter, dentro de um conjunto definido de caracteres. Nas Expressões Regulares, as classes de caracteres são definidas, pondo os caracteres permitidos para a classe entre parêntesis rectos, [], ou usando uma das classes abreviadas descritas em seguida. As classes de caracteres simples contêm apenas um ou mais caracteres literais, como por exemplo [abc] (o que pode corresponder quer a a, a b ou a c), ou então o [0123456789] (que corresponde a qualquer dígito). Dado que as letras e os números têm uma ordem lógica, podê-los-á abreviar, indicando intervalos: o [a-c] é igual a [abc] e o [0-9] é igual a [0123456789]. Combinando estas opções, por exemplo [a-fynot1-38] é perfeitamente possível (a última classe irá corresponder a um dos seguintes caracteres: a,b,c,d, e,f,y,n,o,t, 1,2,3 ou 8). Dado que as letras maiúsculas são caracteres diferentes dos seus equivalentes minúsculos, para criar uma classe de caracteres indiferente da capitalização que corresponda quer a a ou a b em qualquer dos casos, será necessário indicá-la como [aAbB]. Obviamente, é possível criar uma classe negativa que corresponda a tudo excepto. Para o fazer, coloque um acento circunflexo (^) no início da classe: [^abc] irá corresponder a qualquer carácter excepto o a, o b ou o c. Para além dos caracteres literais, estão definidas algumas abreviaturas, o que torna a vida um pouco mais fácil: \a Isto corresponde ao carácter ASCII da campainha (BEL, 0x07). \f Isto corresponde ao carácter ASCII de 'form feed' (FF, 0x0C). \n Isto corresponde ao carácter ASCII de 'line feed' (LF, 0x0A, a mudança de linha do Unix). \r Isto corresponde ao carácter ASCII de 'carriage return' (CR, 0x0D). \t Isto corresponde ao carácter ASCII de tabulação horizontal (HT, 0x09). \v Isto corresponde ao carácter ASCII de tabulação vertical (VT, 0x0B). \xhhhh Isto corresponde ao carácter Unicode com o código hexadecimal 'hhhh' (entre 0x0000 e 0xFFFF). O \0ooo (isto é, \zero ooo) corresponde ao carácter ASCII/Latin-1 com o código octal 'ooo' (entre 0 e 0377). . (ponto) Isto corresponde a qualquer carácter (mesmo à mudança de linha). \d Corresponde a um dígito. É igual a [0-9] \D Corresponde a um não-dígito. É igual a [^0-9] ou [^\d] \s Corresponde a um carácter em branco. É praticamente igual a [ \t\n\r] \S Corresponde a um carácter não-branco. É praticamente igual a [^ \t\r\n] e igual a [^\s] \w Corresponde a qualquer carácter de palavra - neste caso, qualquer letra ou dígito. Repare que o sublinhado (_) não corresponde, como acontece com as expressões regulares do Perl. É igual a [a-zA-Z0-9] \W Corresponde a um não-carácter de palavra - tudo menos letras ou dígitos. É igual a [^a-zA-Z0-9] ou [^\w] As classes abreviadas podem ser postas dentro de uma classe personalizada; por exemplo, para corresponder a um carácter de palavra, a um espaço em branco ou a um ponto, poderia escrever [\w \.] A notação POSIX das classes, [:<nome da classe>:] não é suportada de momento. Os caracteres com significados especiais dentro de classes de caracteres Os seguintes caracteres têm um significado especial dentro da estrutura da classe de caracteres [], devendo ser escapados para serem incluídos literalmente dentro de uma classe: ] Termina a classe de caracteres. Deve ser escapada, a menos que seja o primeiro carácter da classe (pode estar a seguir a um ^ não-escapado) ^ (acento circunflexo) Denota uma classe negativa, se for o primeiro carácter. Deve ser escapado para ser correspondido literalmente, se for o primeiro carácter da classe. - (traço) Denota um intervalo lógico. Deve estar sempre escapado numa classe de caracteres. \ (barra invertida) O carácter de escape. Deve ser sempre escapado. Alternativas: corresponder a <quote >um de</quote > Se quiser corresponder a um elemento de um conjunto de padrões alternativos, podê-los-á separar com o | (carácter de barra vertical). Por exemplo, se quiser encontrar tanto João como Henrique, poderá usar uma expressão João|Henrique. Sub-Padrões Os sub-padrões são padrões colocados dentro de parêntesis, e podem ter várias utilizações no mundo das expressões regulares. Definir alternativas Poderá usar um sub-padrão para agrupar um conjunto de alternativas num padrão maior. As alternativas são separadas pelo carácter | (barra vertical). Por exemplo, para corresponder a uma das palavras int, float ou double, poderia usar o padrão int|float|double. Se só desejar encontrar uma, se estiver seguida de algum espaço e de algumas letras, ponha as alternativas dentro de um sub-padrão: (int|float|double)\s+\w+. Capturar o texto correspondente (referências anteriores) Se desejar usar uma referência anterior, use um sub-padrão para obter a parte desejada do padrão recordado. Por exemplo, se quiser encontrar duas ocorrências da mesma palavra, separadas por uma vírgula e provavelmente por algum espaço, poderia escrever (\w+),\s*\1. O sub-padrão \w+ iria encontrar um conjunto de caracteres de palavra e a expressão inteira iria corresponder, se estas fossem seguidas por uma vírgula, 0 ou mais espaços e por um conjunto igual de caracteres de palavras. (O texto \1 referencia o primeiro sub-padrão entre parêntesis) Verificações Antecipadas Uma verificação antecipada é um sub-padrão que começa por ?= ou por ?!. Por exemplo, para fazer a correspondência com o nome Bill mas só se não for seguido de Gates, podia usar esta expressão: Bill(?! Gates). (Isto iria encontrar o Bill Clinton, assim como o Billy the kid, mas iria ignorar as outras correspondências). Os sub-padrões usados para as verificações não são capturados. Veja também as Asserções ou Verificações Os caracteres com um significado especial dentro de padrões Os seguintes caracteres têm significado próprio dentro de um padrão, e necessitam ser escapados se quiser fazer correspondência com eles: \ (barra invertida) O carácter de escape. ^ (acento circunflexo) Corresponde ao início do texto. $ Verifica o fim do texto. () (parêntesis esquerdo e direito) Denota os sub-padrões. {} (chavetas esquerda e direita) Denota os quantificadores numéricos. [] (parêntesis rectos esquerdo e direito) Denota as classes de caracteres. | (barra vertical) OU lógico; separa as alternativas. + (sinal mais) Quantificador, 1 ou mais. * (asterisco) Quantificador, 0 ou mais. ? (ponto de interrogação) Um carácter opcional. Pode ser interpretado como um quantificador 0 ou 1. Quantificadores Os quantificadores permitem a uma expressão regular fazer a correspondência com um número ou intervalo específico de vezes nas quais ocorre um carácter, classe de caracteres ou sub-padrão. Os quantificadores estão delimitados por chavetas ({ e }) e têm a forma geral {[mínimo-de-ocorrências][,[máximo-de-ocorrências]]} A sua utilização será melhor explicada com um exemplo: {1} Exactamente 1 ocorrência {0,1} Zero ou 1 ocorrências {,1} O mesmo, mas com menos trabalho ;) {5,10} Pelo menos 5, mas no máximo 10 ocorrências. {5,} Pelo menos 5 ocorrências, sem máximo. Adicionalmente, existem algumas abreviaturas: * (asterisco) semelhante a {0,}, encontra qualquer número de ocorrências. + (sinal mais) semelhante a {1,}, pelo menos 1 ocorrência. ? (ponto de interrogação) semelhante a {0,1}, zero ou uma ocorrências. Ganância Ao usar quantificadores sem máximos, as expressões regulares tentam corresponder com o máximo do texto possível, um comportamento designado normalmente como greedy (ambicioso). O 'software' de expressões regulares moderno oferece as opções para desligar esse comportamento, ainda que, num ambiente gráfico, isto dependa da interface que der para a funcionalidade. Por exemplo, uma janela de procura, que ofereça uma pesquisa de expressões regulares, poderia ter uma opção chamada Correspondência mínima, assim como podia indicar se o comportamento ambicioso é o comportamento por omissão. Exemplos no contexto Aqui estão alguns exemplos da utilização de quantificadores ^\d{4,5}\s Corresponde aos dígitos em 1234 go e em 12345 now, mas não corresponde a 567 eleven ou a 223459 somewhere \s+ Corresponde a um ou mais caracteres em branco (bla){1,} Corresponde a tudo de blablabla e a bla em blackbird ou em tabela /?> Corresponde a /> em <closeditem/> assim como a > em <openitem>. Asserções As verificações ou asserções permitem a uma expressão regular fazer a correspondência, apenas sob determinadas condições controladas. Uma verificação não precisa de um carácter com o qual corresponder; em vez disso, verifica os limites de uma possível correspondência antes de a indicar. Por exemplo, a verificação de limite de palavra não tenta encontrar um carácter não pertencente a uma palavra junto com um carácter de palavra, mas sim tenta ter a certeza que não existe um carácter de palavra. Isto significa que a verificação pode corresponder onde não existir um carácter, isto é, no fim do texto a pesquisar. Algumas verificações, de facto, têm um padrão de correspondência, mas a parte do texto que correspondeu não será uma parte do resultado da correspondência, em relação à expressão completa. As Expressões Regulares aqui referidas suportam as seguintes verificações: ^ (acento circunflexo: início do texto) Corresponde ao início do texto a pesquisar. A expressão ^Pedro irá corresponder a Pedro no texto Pedro, olá! mas não em Olá, Pedro! $ (fim do texto) Corresponde ao fim do texto a pesquisar. A expressão tu\?$ irá corresponder ao último 'tu' no texto tu não fizeste isto, ou foste tu? mas não fará correspondência em tu não fizeste isto, certo? \b (limite de palavra) Corresponde a um limite de palavra de um lado e se não é um carácter de palavra do outro. Isto é útil para encontrar limites das palavras como, por exemplo, ambos os extremos para encontrar uma palavra inteira. A expressão \bem\b irá corresponde ao em separado no texto Ele entrou em Enfermagem, mas não corresponder a em na palavra Enfermagem. \B (não-limite de palavra) Corresponde nos locais onde o \b não faz correspondência. Isto significa que ele irá fazer correspondência, por exemplo, dentro de palavras. A expressão \Bem\B irá corresponder a sempre mas não a cem ou a Estou em casa. (?=PADRÃO) (Antevisão positiva) Uma verificação antecipada olha para a parte do texto a seguir a uma possível correspondência. A antecipação positiva irá evitar que o texto corresponda se o texto que se encontra a seguir a possível correspondência não corresponder ao PADRÃO da verificação; o texto correspondente não será incluído no resultado. A expressão utilizar(?=\w) irá corresponder a utilizar em utilizarei, mas não irá corresponder com Não vou utilizar! (?!PADRÃO) (Antevisão Negativa) A antevisão negativa evita que uma possível correspondência seja extraída, se a parte subsequente ao texto procurado corresponder ao PADRÃO. A expressão const \w+\b(?!\s*&) irá corresponder com o const char do texto const char* ola, embora não corresponderá a const QString em const QString& bar porque o & corresponde ao padrão de verificação antecipada negativa.