Como grep linhas, com base em um determinado padrão?

8

Digamos que eu tenha um arquivo contendo as seguintes duas linhas:

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

Eu preciso obter a linha contendo o padrão /aa/bbbb/cccccc apenas, não preciso da segunda linha contendo caracteres extras, ou seja, ?dddddddd . Agora quando eu tentei

grep '/aa/bbbb/cccccc' file

Em seguida, ambas as linhas estão sendo selecionadas. Eu preciso da linha completa, então grep -o não poderia ser uma solução.

Qual poderia ser a solução possível usando grep para que apenas a primeira linha fosse selecionada com base no padrão de pesquisa?

    
por heemayl 16.11.2014 / 12:55

3 respostas

7

Experimente o comando grep abaixo, que usa o parâmetro -P ( Perex-regexp ).

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S) Esse lookbehind negativo afirma que o caractere que precede a string /aa/bbbb/cccccc seria qualquer um, mas não um caractere não espacial.

  • (?!\S) Lookahead negativo afirma que o caractere após a correspondência seria qualquer um, mas não um caractere não espacial.

Outro grep,

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

Através do python,

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

Salve o código acima em um arquivo e nomeie-o como script.py . Em seguida, execute o script acima por

python3 script.py /path/to/the/file/you/want/to/work/with
    
por Avinash Raj 16.11.2014 / 12:58
10

A maneira mais simples seria adicionar um espaço depois do seu padrão:

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou para corresponder a todos os tipos de espaço em branco:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, com uma lookahead positiva :

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, com uma lookahead negativo :

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou você pode reverter a correspondência:

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou para corresponder também às linhas que contêm apenas o padrão (sem espaço em branco):

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

Ou você pode usar apenas um pequeno script:

  • no awk:

    $ awk '=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    Ou, se você não sabe em qual campo seu padrão está

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • Em Perl

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
por terdon 16.11.2014 / 13:50
2

Para complementar @AvinashRaj 's answer , você pode usar também o comando como este.

grep -P '/a+/b+/c+(?!\S)' file
    
por αғsнιη 16.11.2014 / 13:05