grepping uma substring de um resultado grep

4

Dado um arquivo de log, geralmente faço algo assim:

grep 'marker-1234' filter_log

Qual é a diferença no uso de '' ou '' ou nada no padrão?

O comando grep acima irá render muitos milhares de linhas; o que eu desejo. Dentro dessas linhas, geralmente há uma parte dos dados que eu sou depois. Às vezes, eu uso o awk para imprimir os campos que estou procurando. Nesse caso, o formato do log muda, não posso confiar apenas na posição, para não mencionar que os dados reais registrados podem empurrar a posição para frente.

Para tornar isso compreensível, digamos que a linha de log continha um endereço IP, e era tudo o que eu procurava, para depois canalizá-lo para classificar e exclusivo e obter algumas contagens.

Um exemplo pode ser:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: [email protected] to [email protected] [stat-xyz9876]

O primeiro comando grep me dará muitos milhares de linhas como as anteriores, a partir daí, eu quero canalizá-lo para algo, provavelmente sed , que pode extrair um padrão e imprimir apenas o padrão.

Para este exemplo, usar o endereço IP seria suficiente. Eu tentei. O sed não consegue entender [0-9] {1,3}. como um padrão? Eu tive que [0-9] [0-9] [0-9]. que produziu resultados estranhos até todo o padrão criado.

Isto não é específico para um endereço IP, o padrão vai mudar, mas eu posso usar isso como um modelo de aprendizagem.

Obrigado a todos.

    
por user17245 09.04.2010 / 03:18

4 respostas

7

Eu não sei em qual sistema operacional você está, mas no FreeBSD 7.0+ o grep tem uma opção -o para retornar apenas a parte que corresponde ao padrão. Então você poderia grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

Retorna uma lista de apenas endereços IP do 'filter_log' ...

Isso funciona no meu sistema, mas, novamente, eu não sei o que sua versão do grep suporta.

    
por 09.04.2010 / 04:28
3

você pode fazer tudo isso em apenas um comando awk . Não há necessidade de usar outras ferramentas

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)
    
por 09.04.2010 / 04:44
2

Você pode reduzir o segundo grep um pouco assim:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

Para responder a sua primeira pergunta, as aspas duplas permitem que o shell faça várias coisas, como expansão de variáveis, mas proteja alguns metacaracteres da necessidade de serem escapados. As aspas simples impedem que o shell faça essas expansões. Não usar citações deixa as coisas abertas.

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

Você pode aprender mais na seção "QUOTING" de man bash

    
por 09.04.2010 / 06:16
1

Procure o comando xargs . Você deveria ser capaz de fazer algo como:

grep 'marker-1234' filter_log|xargs grep "("|cut -c1-15

Isso pode não ser exatamente, mas xargs é o comando que você quer usar

    
por 09.04.2010 / 03:38

Tags