grep: muestra el nombre del archivo una vez, luego muestra el contexto con números de línea

16

Nuestro código fuente tiene códigos de error dispersos por todas partes. Encontrarlos es fácil con grep, pero me gustaría una función bash find_codeque pueda ejecutar (por ejemplo find_code ####), que proporcionará resultados a lo largo de estas líneas:

/home/user/path/to/source.c

85     imagine this is code
86     this is more code
87     {
88         nicely indented
89         errorCode = 1111
90         that's the line that matched!
91         ok this block is ending
92     }
93 }

Esto es lo que tengo actualmente:

find_code()
{
    # "= " included to avoid matching unrelated number series
    # SRCDIR is environment variable, parent dir of all of projects
    FILENAME= grep -r "= ${1}" ${SRCDIR}
    echo ${FILENAME}
    grep -A5 -B5 -r "= ${1}" ${SRCDIR} | sed -e 's/.*\.c\[-:]//g'
}

Problemas:

1) Esto no proporciona números de línea

2) solo coincide con los archivos fuente .c. Tengo problemas para que sed coincida con .c, .cs, .cpp y otros archivos de origen. Sin embargo, usamos C, por lo que simplemente coincide - o: (los caracteres que grep agrega al nombre de archivo antes de cada línea de código) coincide object->pointersy desordena todo.

TravisThomas
fuente

Respuestas:

11

Cambiaría algunas cosas al respecto.

find_code() { 
    # assign all arguments (not just the first ${1}) to MATCH
    # so find_code can be used with multiple arguments:
    #    find_code errorCode
    #    find_code = 1111
    #    find_code errorCode = 1111
    MATCH="$@" 

    # For each file that has a match in it (note I use `-l` to get just the file name
    # that matches, and not the display of the matching part) I.e we get an output of:
    #
    #       srcdir/matching_file.c
    # NOT:
    #       srcdir/matching_file.c:       errorCode = 1111
    #
    grep -lr "$MATCH" ${SRCDIR} | while read file 
    do 
        # echo the filename
        echo ${file}
        # and grep the match in that file (this time using `-h` to suppress the 
        # display of the filename that actually matched, and `-n` to display the 
        # line numbers)
        grep -nh -A5 -B5 "$MATCH" "${file}"
    done 
}
Drav Sloan
fuente
Ajusté esto de nuevo a mis especificaciones, simplemente quiero buscar códigos de error. Por lo tanto MATCH="= ${1}". También agregué --include=*.c --include=*.cpp --include=*.java --include=*.cspara limitar la búsqueda a los archivos de origen. ¡Gracias!
TravisThomas
1
Bien, me alegro de que hayas logrado
ajustarlo
3

Usted podría utilizar findcon dos -execs, la segunda sólo se ejecutará si el primero tiene éxito, es decir, buscar sólo en .cpp, .cy .csarchivos:

find_code() {
find ${SRCDIR} -type f \
\( -name \*.cpp -o -name \*.c -o -name \*.cs \) \
-exec grep -l "= ${1}" {} \; -exec grep -n -C5 "= ${1}" {} \;
}

así que el primero grepimprime los nombres de archivo que contienen su patrón y el segundo imprime las líneas coincidentes + contexto, numeradas, de los archivos respectivos.

don_crissti
fuente