quarta-feira, 17 de dezembro de 2014

Trabalhando com File Glob e Expressões Regulares

Muito usado em pesquisa de arquivos, File Glob é uma forma de fazer referência a vários arquivos usando uma única expressão. As mais conhecidas, também usadas na linha de comandos do Windows, são o asterisco "*" e o sinal de interrogação "?".

O "?" substitui um único caracter no nome do arquivo. Por exemplo, vamos supor que você tem uma pasta com os seguintes arquivos:

$ ls
carta1.odt  carta4.odt      carta_ext2.odt  ci1.odt  memorando1.odt
carta2.odt  carta5.odt      carta_ext3.odt  ci2.odt  memorando2.odt
carta3.odt  carta_ext1.odt  carta.odt        ci3.odt  memorando3.odt

Para listar os arquivos "carta1.odt", "carta2.odt", etc, mas não "carta.odt", digite.

$ ls carta?.odt
carta1.odt  carta2.odt  carta3.odt  carta4.odt  carta5.odt

O "*" substitui uma sequência qualquer de caracteres, inclusive nenhum. Para listar todos os arquivos que possuem "memorando" no nome, digite:

$ ls memorando*
memorando1.odt  memorando2.odt  memorando3.odt

Outro exemplo, vamos listar todos os arquivos que começam com "carta".

$ ls carta*
carta1.odt  carta3.odt  carta5.odt        carta_ext2.odt  carta.odt
carta2.odt  carta4.odt  carta_ext1.odt  carta_ext3.odt

Reparem que, ao contrário do "?", o "*" também listou o arquivo carta.odt.

Mas há ainda outras construções que não existem no ambiente Windows. Para listar todas as cartas com número 1 até 3 digite:

$ ls carta[123]*
carta1.odt  carta2.odt  carta3.odt

Essa construção considera todos os caracteres dentro de "[]". Para listar, por exemplo, "menino.txt" e "menina.txt" poderíamos usar "menin[ao].txt".

Outra forma é a seguinte:

$ ls carta[1-3]*
carta1.odt  carta2.odt  carta3.odt

O "-" diz "do primeiro caracter até o último". Se quiséssemos listar todos os arquivos que comaçam com números poderíamos usar "[0-9]*".

Podemos usar a negação "^". Para listar todos os arquivos que NÃO sejam de 1 a 3 digitamos:

$ ls carta[^1-3]*
carta4.odt  carta5.odt  carta_ext1.odt  carta_ext2.odt  carta_ext3.odt  carta.odt

Se eu não quiser "carta_ext", basta incluir o caracter "_" no comando acima.

$ ls carta[^1-3_]*
carta4.odt  carta5.odt  carta.odt

Você pode querer também listar todos os arquivos "carta" e "memorando". Para isso, use o "{}".

$ ls {carta,memorando}*
carta1.odt  carta2.odt  carta3.odt  carta4.odt  carta5.odt  carta_ext1.odt  carta_ext2.odt carta_ext3.odt  carta.odt  memorando1.odt  memorando2.odt  memorando3.odt

Reparem que "ci" não foi mostrado.

Essas regras podem ser misturadas. Por exemplo, para mostrar todos os arquivos "carta" ou "memorando" mas que sejam de 3 até 5, digite:

$ ls {carta,memorando}[3-5]*
carta3.odt  carta4.odt  carta5.odt  memorando3.odt

A tabela abaixo resume as opções de File Glob

*
Qualquer coisa
*.txt
?
Um caractere qualquer
arquivo-??.zip
[...]
Qualquer um dos caracteres listados
[Aa]rquivo.txt
[^...]
Qualquer um caractere, exceto os listados
[^A-Z]*.txt
{...}
Qualquer um dos textos separados por vírgula
arquivo.{txt,html}

Já as expressões regulares, ou REGEX, são expressões usadas para referenciar várias sentenças. São muito parecidas com o FileGlob, mas são usadas para pesquisa de texto. Por exemplo, o ponto (.) é usado para substituir um caracter. Já a barra invertida (\) diz que o próximo carcter deve ser interpretado literalmente. Por exemplo, para listar todos os sites dos tribunais regionais estaduais você pode fazer a seguinte regex:

trt\...\.gov\.br

Em outras palavras a regex acima diz para trazer qualquer texto que tenha a string "trt" seguida de um ponto literal (\.) seguida de dois caracteres quaisquer (..) seguida de outro ponto literal (\.) seguida do texto "br".

trt.sp.gov.br
trt.rj.gov.br
trt.ms.gov.br

Se eu quiser apenas os tribunais do Mato Grosso e do Mato Grosso do Sul posso usar o [] para referenciar todos os caracteres que podem aparecer na posição.

trt\.m[st]\.gov\.br

Se quisermos todos os tribunais menos os do Distrito Federal e do Ceará usamos o caracter de negação (^).

trt\.[^cd].\.gov\.br

Uma regex que uso bastaste é para omitor as linhas em branco de um arquivo texto . Para isso uso os posicionadores "^" (começo de linha) e o "$" (fim de linha).

grep -v ^$ arquivo.txt

No comando acima estou pedindo para o grep listar todas as linhas do arquivo "arquivo.txt"" com excessão (-v) daquelas que começam (^) e logo em seguida terminam ($), ou seja, as linhas em branco.

Em meus filtros de conteúdo eu costumo bloquear todos os sites que são acessados por IP. Para isso posso usar a regex {}. Por exemplo, para se referir a qualquer número de 0 a 999, uso a seguinte expresão.

grep -E '^[0-9]{1,3}' arquivo.txt

A regex {a,b} nos diz que a sequência anterior deverá se repetir pelo menos "a" vezes e no máximo "b" vezes. Se quisermos um número com exatos 3 algarismos, podemos usar [0-9]{3,3}. Se quisermos 3 ou mais vezes usamos [0-9]{3,}

Logo, para fazer referência a um endereço IP no começo da URL eu posso usar o seguinte:

^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

Abaixo segue um resumo das expressões regulares.

Meta Nome Descrição
. Ponto Curinga de um caractere
[] Lista Casa qualquer um dos caracteres listados
[^] Lista negada Casa qualquer caractere, exceto os listados
? Opcional O item anterior pode aparecer ou não (opcional)
* Asterisco O item anterior pode aparecer em qualquer quantidade
+ Mais O item anterior deve aparecer no mínimo uma vez
{,} Chaves O item anterior deve aparecer na quantidade indicada {mín,máx}
^ Circunflexo Casa o começo da linha
$ Cifrão Casa o fim da linha
\b Borda Limita uma palavra (letras, números e sublinhado)
\ Escape Escapa um metacaracter, tirando seu poder
| Ou Indica alternativas (usar com o grupo)
() Grupo Agrupa partes da expressão, é quantificável e multinível
\1 Retrovisor Recupera o conteúdo do grupo 1
\2 Retrovisor Recupera o conteúdo do grupo 2 (segue até o \9)
.* Curinga Casa qualquer coisa, é o tudo e o nada
?? Opcional NG Idem ao opcional comum, mas casa o mínimo possível
*? Asterisco NG Idem ao asterisco comum, mas casa o mínimo possível
+? Mais NG Idem ao mais comum, mas casa o mínimo possível
{}? Chaves NG Idem às chaves comuns, mas casa o mínimo possível
Para saber mais sobre esse assunto eu recomendo o site http://aurelio.net/shell/canivete e o livro Programação Shell Script de Julio Cezar Neves.