sexta-feira, 16 de março de 2012

Oficina do eBook: Regex

Aumentar Letra Diminuir Letra


Hoje vou fazer um texto rápido sobre algo que não faz parte dos e-books, mas é uma ferramenta que aumenta em muita a sua produtividade para trabalhar com eles, trata-se das regex.
Regex ou expressões regulares são partes de um mecanismo de busca e substituição de conteúdo de texto que otimiza certas buscas.
Por exemplo se eu tenho o conteúdo abaixo.

<a id="texto.html" />

E quero remover a extensão do título de id eu usaria a seguinte regex no campo de busca.

(<a id=")(.*).html(" />)

e no campo de substituição eu colocaria o seguinte conteúdo.

\1\2\3

Como resultado eu teria o seguinte.


<a id="texto" />

Claro pra apenas uma substituição esse trabalho seria tolice, mas quando eu tenho um padrão bem estabelecido para busca e substituição o regex é uma mão na roda.
Vamos entender um pouco mais.
A expressão (<a id=")(.*).html(" />) que usamos no exemplo contem alguns caracteres de comando e parte do texto a ser procurado. Os Parênteses ( ) servem apenas para dividir a busca em campos sendo que cada par de parênteses corresponde a um grupo isso é utilizado na substituição pois quando usamos \1 estamos nos referenciando ao primeiro grupo \2 ao segundo e \3 ao terceiro.
dentro do grupo 2 temos como conteúdo .* aí temos dois comandos o primeiro . significa um caracter qualquer já o segundo * significa quantas repetições forem necessárias, ou seja o conjunto diz que no grupo dois temos qualquer número de quaisquer caracteres isso permite que você tenha o conteúdo que quiser do tamanho que quiser ele só para a leitura quando achar o conjunto de caracteres seguintes que é .html. O resto da expressão faz parte do conteúdo da busca.
Entretanto ainda a um detalhe a ser observado o ponto em .html faz referência a um caracter qualquer e não a um ponto, entretanto como na busca temos um ponto ele bate como um caracter qualquer, mas se o id fosse como mostrado abaixo.


<a id="texto$html" />

Não conseguiríamos um bom resultado usando a expressão (<a id=")(.*)$html(" />), isso porque $ também é um comando de regex mas este faz referência ao fim de uma linha e não a um caracter qualquer, logo ele não se auto-referência como o ponto . no primeiro exemplo.
Para resolver isso devemos usar a barra invertida \ pois esta barra é um comando que diz ao regex para interpretar o comando seguinte como caracter logo \$ diz respeito ao caracter $ enquanto que apenas $ diz respeito ao fim de uma linha.

Abaixo tem uma pequena lista de comandos para o regex.

Um caracter qualquer
( ) Marca uma região para referência na substituição
\n Faz referência ao grupo que deve ser copiado \1 para grupo um, \2 para grupo dois , etc. \0 representa toda a sentença que foi pesquisada
\<Referência ao começo de uma palavra
\>Referência ao fim de uma palavra
\xpermite usar o comando que x representa como caracter por exemplo \. representa um ponto e não qualquer caracter
[]Indica um grupo de caracteres, por exemplo [abc] procurará por a ou b ou c no texto [ABC] procurará A ou B ou C. Você também pode usar um conjunto por exemplo [a-z] procurará por qualquer letra em caixa baixa já [0-9] procura por qualquer número.
[^ ]Procura por qualquer caracter com exceção dos descritos. por exemplo [^0-9] procurará por qualquer caracter que não seja número.
^Referência ao começo de linha, não pode estar entre colchetes pois aí entraria na regra acima
$Referência ao fim da linha
*Procura pelo resultado 0 ou mais vezes
+Procura pelo resultado 1 ou mais vezes
?Procura pelo resultado 0 ou 1 vez
|Alternativa por exemplo a|b significa encontre a ou b

Dica final.
Muitas vezes em conversões de documentos pdf temos quebra de linhas estranhas para resolver isso no sigil você pode tentar a seguinte expressão.


([^\.\?\:\!])</p>
<p>

Substituir por

\1

Isto porque um parágrafo sempre termina com um ponto final, interrogação dois pontos ou exclamação, desta forma você elimina todas as quebras de linha sem justificação, apenas tenha cuidado com os títulos e veja se não há casos em que os dois pontos seguiriam na mesma linha.
Outro ponto interessante é marcar os títulos como <h1> ou outro que indique se tratar de um título pois aí ele não entra na busca já que não usará o <p>

8 comentários:

  1. Eu acho muito legal essas postagens da oficina do ebook, mas eu não consegui entender esse post em especial.

    ResponderExcluir
    Respostas
    1. Qual parte ficou complicada?
      É um pouco difícil não ser prolixo nesses assuntos.

      Excluir
    2. Eu entendi para que serve. Mas quando surgiu o exemplo
      "<a id="texto.html" / >"
      Não entendi o que cada parte do comando representa. Assim como não entendi o \1\2\3.

      Excluir
    3. Quando você coloca uma parte da expressão entre parênteses você cria um bloco, esses blocos são ordenados à partir do 1
      como no exemplo tinha 3 pares de parênteses, você tem três blocos.
      Quando você coloca \1\2\3 você está referenciando cada bloco sendo \1 para o primeiro \2 o segundo e \3 o terceiro.
      o seja \1\2\3 é igual copie bloco 1 2 e 3.

      Excluir
  2. Você poderia fazer outro exemplo? Um que realmente ocorra a substituição? Porque, pelo que entendi, nos dois exemplos dados só ocorreu a eliminação de um elemento indesejado.

    ResponderExcluir
    Respostas
    1. por exemplo para substituir trecho em negrito por um parágrafo que use uma classe de estilo com negrito você buscaria por

      <b>(.*)</b>

      e subsituir por

      <p class="negrito">\1 </p>

      Excluir
    2. Acho que entendi. Muito obrigado.

      Excluir
  3. Paulo eu tenho uma sequencia de código que talvez consiga exclui de maneira mais simples. Trata-se das páginas que vieram de um pdf para um epub. Olhando pelo Sigil, a sequencia é essa div class="sgc-1"> ?? /div>, onde ?? é o número das páginas. Teria alguma forma de eu excluir esse código por completo?

    Abraço

    ResponderExcluir