Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Curso de Shell - Aula 5

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Curso de Shell - Aula 5


    Por: Alex Borro

    Nesta aula teremos um breve tutorial sobre o Grep. Ele não é somente um dos comandos mais úteis, mas o seu domínio abre portas para dominar outros poderosos comandos, como o sed (que trataremos na próxima aula) , awk, perl, etc.

    Eu fiz uma adaptação/ modificação de um tutorial que eu tenho, e por sinal é excelente, sobre o Grep e Expressões Regulares em inglês. Espero que tenha ficado legal e vocês gostem.

    O que ele faz?

    O grep basicamente faz buscas. Mais precisamente:

    grep palavra file retorna todas as linhas do arquivo file
    que contenham palavra

    Outro jeito de usar o grep é atraves de pipe (lembram dos pipes?). Por exemplo:

    ls | grep palavra

    Lista todos os arquivos que contenham palavra em seu nome. Ou seja, a entrada do grep é uma lista de arquivos (gerada pelo ls) que será filtrada, sendo impressas somente as linhas que contenham palavra.

    Usando caracteres coringas

    Suponho que todos saibam o que são caracteres coringas. Caso contrário, coringas são caracteres especiais que substituem outros. Geralmente o caracter "*" é um coringa que significa "qualquer caracter em qualquer quantidade". Por isso se a gente executar "ls *", onde "*" entra no lugar do "nome do arquivo", significando qualquer string de qualquer tamanho. Por isso ele lista todos os arquivos.

    Mas agora voltemos ao grep. Será que ele aceita coringas ??? A resposta é mais do que sim. O grep suporta algo que vai além de coringas, ele suporta Expressões Regulares. Mas vamos começar apenas com coringas. Um dos mais usados com o grep é o "." Vamos a um exemplo:

    >cat file >grep b.g
    file
    big big
    bad bug bad bug
    bigger bigger
    boogy


    Note que boogy não casa, desde que "." significa "qualquer e apenas um caracter". Para significar strings arbitrárias utilizamos "*", que funciona da seguinte maneira:

    "A expressão consistindo de um caracter seguido por um * casa com qualquer número (inclusive zero) de repetições desse caracter. Em particular, ".*" significa qualquer string."

    Para compreendermos vamos a mais exemplos:

    >cat file
    big
    bad bug
    bag
    bigger
    boogy>grep b.*g file
    big
    bad bug
    bag
    bigger
    boogy>grep b.*g. File
    bigger
    boogy>grep ggg* file
    bigger

    Avançando para expressões regulares

    Os coringas são o começo, mas a idéia vai mais longe. Por exemplo, suponha que queremos uma expressão que case com Frederic Smith ou Fred Smith, ou seja, a string "eric" é opcional.

    Primeiro, introduzimos o conceito de um "caracter escapado (escaped character)".

    "Um caracter escapado é um caracter precedido por uma barra invertida ( \ ). Essa barra invertida faz o seguinte: (a) Remove qualquer significado especial do caracter. (b) acrescenta um significado especial a um caracter que não tenha um significado especial."

    Parece complicado, mas veja nos exemplo que é um tanto quanto simples:

    Para procurar uma linha contento o texto "hi.gif", o comando correto seria:

    grep 'hi\.gif' file

    Desde que "grep 'hi.gif' file" iria resultar linhas contendo: hi-gif , hello1gif , helloagif , etc.

    Ou seja, a barra invertida remove o significado especial do ".", passando esse a significar um simples ponto ao invés de um coringa.

    Agora vamos passar para expressões agrupadas, a fim de encontrar um jeito de criar uma expressão que case com Frederic ou Fred. Primeiro vamos começar com o operador "?":

    "Uma expressão consistindo de caracter seguido por uma interrogação escapada ( \? ) casa com zero ou uma instância daquele caracter".

    Exemplo:

    "bugg\?y" casa com o seguinte: bugy , buggy mas não com
    bugggy

    neo@matrix:~$ echo bugy | grep "bugg\?y"
    bugy
    neo@matrix:~$ echo bugggy | grep "bugg\?y"
    neo@matrix:~$

    Agora vamos para expressões agrupadas. No nosso exemplo, queremos tornar opcional a string "eric" após "Fred", ou seja, não apenas um caracter mas sim um conjunto de caracteres (string).

    "Uma expressão dentro de parênteses escapados é tratada como um único caracter"

    Exemplos:

    "Fred\(eric\)\?" Smith casa com "Fred Smith" or "Frederic Smith"
    \(abc\)* casa com abc , abcabcabc, etc (isto é, qualquer
    número de repetições da string "abc", incluindo
    zero).

    Note que temos que tomar cuidado quando nossas expressões contém espaços em branco. Quando eles aparecem, precisamos colocar a expressão entre aspas, para que o shell não interprete mal nosso comando. Para o exemplo acima:

    grep "Fred\(eric\)\? Smith" file

    Eu aconselho fortemente a sempre usar aspas, mesmo que não usemos espaços em brancos. Já tive muita dor de cabeça porque expressões e comandos não funcionavam simplesmente por não estarem entre aspas. Um dos exemplo acima (o do bugg\?y) não funciona no meu sistema se não estiver entre aspas. Veja:

    neo@matrix:~$ echo bugy | grep "bugg\?y"
    bugy
    neo@matrix:~$ echo bugy | grep bugg\?y
    neo@matrix:~$

    Outros operadores úteis

    Para casar algum caracter de uma lista, use [ ] Veja:

    "[Hh]ello" casa com linhas contendo "hi" ou "hi"

    Faixas de caracteres também são permitidos:

    [0-3] é o mesmo que [0123]
    [a-k] é o mesmo que [abcdefghijk]
    [A-C] é o mesmo que [ABC]
    [A-Ca-k] é o mesmo que [ABCabcdefghijk]

    Existem também algumas formas alternativas:

    [[:alpha:]] é o mesmo que [a-zA-Z]
    [[:upper:]] é o mesmo que [A-Z]
    [[:lower:]] é o mesmo que [a-z]
    [[:digit:]] é o mesmo que [0-9]
    [[:alnum:]] é o mesmo que [0-9a-zA-Z]
    [[:space:]] casa com qualquer quantidade de espaços,
    inclusive tabulações

    Essas formas alternativas, como [[:digit:]] é preferível ao método direto, [0-9].

    Os [ ] podem ser usado para indicar caracteres que NÃO devem estar na expressão. É só colocar o sinal ^ na primeira posição da lista. Veja:

    neo@matrix:~$ echo hi | grep "[Hh]ello"
    hi
    neo@matrix:~$ echo hi | grep "[^Hh]ello"
    neo@matrix

    Outro exemplo, um pouco mais complicado:

    grep "([^()]*)a" file retorna qualquer linha contendo um par de parentes seguido por "a" e que NÃO contenham outros parênteses dentro. Assim, ele casa com essas linhas:

    (hi)a
    (aksjdhaksj d ka)a

    Mas não com: x=(y+2(x+1))a

    Casando com um número especifico de repetições

    Suponha que você queira casar um número específico de repetições de uma expressão. Um bom exemplo são números de telefones. Você pode procurar por um número de telefone com sete dígitos, assim:

    grep "[:digit:]\{3\}[ -]\?[:digit:]\{4\}" file

    Ou seja, três dígitos, opcionalmente um espaço ou um hífen e mais 4 dígitos.

    Procurando por começo e fim de linha:

    Isso é muito Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar.... Digamos que você queira procurar por linhas que contendo espaços em brancos no começo da linha, a palavra hi e então o fim da linha. Vamos começar com este exempo:

    >cat file
    hi
    hi world
    hhello

    >grep hi file
    hi
    hi world
    hhello

    Isso não é o que nós queremos. O que está errado ? O problema é que o grep procura por linhas contendo a string hi e todas as linhas especificadas contem ela. Para contornar isso, introduzimos os caracteres de começo e fim de linha:

    "O caracter ^ significa começo de linha e o $ significa fim da linha"

    Retornando ao nosso exemplo:

    grep "^[[:space:]]*hi[[:space:]]*$" file

    Ou seja, o começo da linha, qualquer quantidade de espaço em branco (inclusive zero), a palavra hi, qualquer quantidade de espaço em branco e o fim da linha. Essa expressão faz o que a gente quer, retornando somente a linha que contém a palavra hi. Outro exemplo:

    grep "^From.*Alex" /var/spool/mail/neo

    Procura no meu inbox por mensagens de uma pessoa em particular (no caso, Alex). Esse tipo de expressão regular é extremamente útil e filtros de e-mail, como o procmail, utilizam isso para fazerem tudo.

    Isso ou Aquilo: Procurando uma coisa OU outra:

    "A expressão consistindo de duas expressões separadas pelo operador OU \| casa linhas contendo uma das duas expressões"

    Note que você DEVE colocar a expressão dentro de aspas simples ou duplas:

    grep "cat\|dog" file casa com linhas contendo a palavra "cat" ou a
    palavra "dog"
    grep "I am a \(cat\|dog\)" casa com linhas contendo a string "I am
    a cat" ou a string "I am a dog".

    Usando backreference (referencia anterior)

    Digamos que você queira procurar strings que contenham uma substring em mais de um lugar. Um exemplo é as tags de cabeçalhos de HTML. Suponha que eu queira procurar por "
    alguma string

    ". Isto é fácil de se fazer. Mas suponha que eu queira fazer o mesmo, mas permita H2 H3 H4 H5 e H6 no lugar de H1. A expressão .* não é boa, desde que casa com "alguma string

    " e nos queremos que a tag de abertura seja igual a de fechamento. Para fazermos isso, usamos backreference:

    "A expressão \n onde n é um número, casa com o conteúdo do n-ésimo conjunto de parênteses na expressão".

    Nossa... isso realmente precisa de um exemplo!!!!

    .* faz o que nos queríamos fazer acima...

    "O Senhor \(dog\|cat\) e a senhora \1 foram visitar o Senhor \(dog\|cat\) e a senhora \2"

    Esse é outro exemplo bobo. Os casais tem sempre que serem iguais. Ou um casal de cachorro ou de gato.

    Alguns detalhes cruciais: caracteres especiais e aspas

    Caracteres Especiais:

    Aqui nós descrevemos os caracteres especiais para RegExp (expressões regulares) no grep. Note que no "egrep", que usa expressões regulares estendidas (atualmente não tem nenhuma funcionalidade a mais que as expressões regulares normais do GNU grep), a lista de caracteres especiais são os mesmos, diferindo somente que alguns não precisar estar "escapados".

    Os seguintes caracteres são considerados especiais, e precisam estar escapados:

    ? \ . [ ] ^ $

    Note que o sinal de $ perde seu sentido se tiver caracteres depois dele, do mesmo jeito que o sinal ^ perde seu sentido se tiver caracteres antes dele. Os colchetes [ ] comportam-se um pouco diferente. A baixo segue as regras para eles:

    * O colchete direito ( ] ) perde seu sentido especial se colocado no começo de uma lista, por exemplo: "[]12]" casa com ] , 1, or 2.
    * Um hífen perde seu significado especial se colocado por último. Assim, [15-] casa com 1, 5 ou -
    * O caracter ^ perde seu sentido se não for colocado em primeiro lugar.
    * A maioria dos caracteres especiais perdem seu significado especial se forem colocados dentro de colchetes.

    Aspas:

    Em primeiro lugar, aspas simples são mais seguras de usar porque elas protegem suas expressões regulares de serem alteradas pelo bash (como foi visto nas aulas anteriores). Por exemplo, grep "!" file vai produzir um erro, já que o shell pensa que "!" está se referindo ao comando de histórico do shell, enquanto grep '!' file funciona perfeitamente.

    Quando você deve usar aspas simples ? A resposta é: se você precisa usar variáveis do shell, use aspas duplas. Caso contrário, use aspas simples. Por exemplo:

    grep "$HOME" file

    Procura em file pelo nome do seu diretório pessoal, enquanto grep '$HOME' file procura pela string $HOME.

    Sintaxe das expressões regulares estendidas

    Agora vamos ver a sintaxe do egrep em contraste com a sintaxe do grep. Ironicamente, apesar do nome "estendido", o egrep atualmente tem menos funcionalidade do que quando foi criado, para manter a compatibilidade com o tradicional grep. A melhor maneira de fazer um grep estendido é utilizar grep -E que usa a sintaxe de expressões regulares estendidas sem perda de funcionalidade.

    Bom, espero que vocês tenham tido uma boa idéia de como funcionam as expressões regulares. Elas são extremamente Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar..., principalmente para utilizar o grep e o poderosíssimo sed, do qual trataremos na próxima aula. Não se preocupem se estiverem confuso com as expressões, quando começarem a utilizá-las, as Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... vão clareando. Até a próxima.
    Mesmo longe, eu estou perto. Guia do Hacker 4ever.
X
Working...
X