grep: affiche le nom de fichier une fois, puis affiche le contexte avec les numéros de ligne

16

Notre code source a des codes d'erreur dispersés partout. Les trouver est facile avec grep, mais j'aimerais une fonction bash find_codeque je peux exécuter (par exemple. find_code ####) Qui fournira une sortie dans ce sens:

/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 }

Voici ce que j'ai actuellement:

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'
}

Problèmes:

1) Cela ne fournit pas de numéros de ligne

2) il ne correspond qu'aux fichiers source .c. J'ai du mal à faire correspondre sed avec .c, .cs, .cpp et d'autres fichiers sources. Nous utilisons cependant C, donc il suffit de faire correspondre - ou: (les caractères que grep ajoute au nom de fichier avant chaque ligne de code) correspond object->pointerset gâche tout.

TravisThomas
la source

Réponses:

11

Je voudrais changer quelques choses.

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
la source
J'ai ajusté cela à mes spécifications - je veux simplement rechercher les codes d'erreur. Alors MATCH="= ${1}". J'ai également ajouté --include=*.c --include=*.cpp --include=*.java --include=*.cspour limiter la recherche aux fichiers source. Merci!
TravisThomas
1
Bon oh, heureux que vous ayez réussi à le régler avec
précision
3

Vous pouvez utiliser findavec deux -execs, la seconde ne sera exécutée que si le premier est réussi, par exemple la recherche uniquement .cpp, .cet .csfichiers:

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

de sorte que le premier grepimprime les noms de fichiers qui contiennent votre modèle et le second imprimera les lignes correspondantes + le contexte, numérotés, à partir des fichiers respectifs.

don_crissti
la source