¿Cómo grep líneas, basadas en un cierto patrón?

8

Digamos que tengo un archivo que contiene las siguientes dos líneas:

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

Necesito obtener la línea que contiene el patrón /aa/bbbb/ccccccsolamente, no necesito la segunda línea que contiene caracteres adicionales, es decir ?dddddddd. Ahora cuando lo intenté

grep '/aa/bbbb/cccccc' file

Luego se seleccionan las dos líneas. Necesito la línea completa, así grep -oque no podría ser una solución.

¿Cuál podría ser la posible solución usando grep para que solo se seleccione la primera línea en función del patrón de búsqueda?

heemayl
fuente

Respuestas:

7

Pruebe el siguiente comando grep que utiliza el parámetro -P( Perl-regexp ).

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)Esta mirada hacia atrás negativa afirma que el carácter que precede a la cadena /aa/bbbb/ccccccsería cualquier carácter que no sea espacio.

  • (?!\S) La búsqueda anticipada negativa afirma que el personaje que sigue a la coincidencia sería cualquier personaje que no sea espacio.

Otro grep,

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

A través de pitón,

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='')

Guarde el código anterior en un archivo y asígnele el nombre script.py. Luego ejecute el script anterior por

python3 script.py /path/to/the/file/you/want/to/work/with
Avinash Raj
fuente
Gracias hombre. Por cierto, ¿se puede hacer esto utilizando expresiones regulares / extendidas en lugar de expresiones regulares perl?
heemayl
1
como terdon publicado, podrías simplementegrep '/aa/bbbb/cccccc ' file
Avinash Raj
Pero lo anterior no imprimirá las líneas que solo tienen /aa/bbbb/cccccccadena.
Avinash Raj
También puedes combinar eso congrep -E '/aa/bbbb/cccccc(\s+|$)' file
terdon
sí, asígrep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Avinash Raj
10

La forma más sencilla sería agregar un espacio después de su patrón:

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

O, para que coincida con todo tipo de espacios en blanco:

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

O

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

O, con una anticipación positiva :

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

O, con una anticipación negativa :

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

O puedes revertir el partido:

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

O, para coincidir también con las líneas que contienen nada más que su patrón (sin espacios en blanco al final):

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

O bien, puede usar un pequeño script:

  • En awk:

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

    O, si no sabe en qué campo está su patrón

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

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
terdon
fuente
@terdon grep -v 'c?' filepor qué no lo usas grep -v '?' fileporque el archivo solo tiene dos líneas.
αғsнιη
@KasiyA cierto, solo quería mantener un poco el patrón. Sin embargo, tienes toda la razón, en este caso particular, grep -v '?'sería suficiente.
terdon