grep: tampilkan nama file satu kali, lalu tampilkan konteks dengan nomor baris

16

Kode sumber kami memiliki kode kesalahan yang tersebar di seluruh. Menemukannya mudah dengan grep, tapi saya ingin fungsi bash find_codeyang dapat saya jalankan (mis. find_code ####) Yang akan memberikan output di sepanjang baris ini:

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

Inilah yang saya miliki saat ini:

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

Masalah:

1) Ini tidak memberikan nomor baris

2) hanya cocok dengan file sumber .c. Saya mengalami masalah untuk menyesuaikan data dengan .c, .cs, .cpp, dan file sumber lainnya. Kami menggunakan C, jadi hanya mencocokkan - atau: (karakter yang grep ditambahkan ke nama file sebelum setiap baris kode) cocok object->pointersdan mengacaukan semuanya.

TravisThomas
sumber

Jawaban:

11

Saya akan mengubah beberapa hal tentang.

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
sumber
Saya menyesuaikan ini kembali ke spesifikasi saya - Saya hanya ingin mencari kode kesalahan. Jadi MATCH="= ${1}". Saya juga menambahkan --include=*.c --include=*.cpp --include=*.java --include=*.csuntuk membatasi pencarian ke file sumber. Terima kasih!
TravisThomas
1
Bagus oh, senang Anda berhasil menyesuaikannya dengan kebutuhan Anda :)
Drav Sloan
3

Anda dapat menggunakan finddua -execs, yang kedua hanya akan dieksekusi jika yang pertama berhasil, mis. Hanya mencari di .cpp, .cdan .csfile:

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

jadi yang pertama grepmencetak nama file yang berisi pola Anda dan yang kedua akan mencetak baris yang sesuai + konteks, diberi nomor, dari masing-masing file.

don_crissti
sumber