What grep command will include the current function name in its output?

前端 未结 9 2065
夕颜
夕颜 2021-01-07 18:08

I run diff with the -p option so the output will include the name of the function where each change occurred. Is there an analogous option for

相关标签:
9条回答
  • 2021-01-07 18:26

    Here is an imperfect solution. It has the following flaws:

    1. It requires a tool called ctags
    2. Consequently, it works for C files, or any languages that ctags supports, but not beyond that
    3. It displays all C function headers, no matter what. This is the biggest problem with my script, you might be able to find a way to overcome it.

    I called my script `cgrep.sh', which has the following syntax:

    cgrep.sh search-term files...
    

    Cgrep.sh works by relying on ctags to produce a list of search patterns for function headers. We can then search for both the function headers and the search term. Without further ado, here is cgrep.sh:

    #!/bin/sh
    
    # Grep, which includes C function headers
    # cgrep term files*
    
    TERM=$1                             # Save the search term
    shift
    
    ctags "$@"                          # produces the tags file
    sed -i.bak 's:^.*/^:^:;s:/$::' tags # Prepare the tags file for grep
                                        # Original contents is backed up to tags.bak
    grep -f tags -e $TERM "$@"          # Grep both headers and search term
    rm tags tags.bak                    # Clean up
    
    0 讨论(0)
  • 2021-01-07 18:33

    Actually "grep -p" has been a fixture in AIX for the last two decades from what I can recall. It is out there, and it's just a matter of porting the behaviour over in fresh code.

    It's crude, though, and may need help to know that blank lines within a function don't count.

    0 讨论(0)
  • 2021-01-07 18:34

    I wrote a script to grep C files and show the C function names and signature along with the results. Based on ctags.

    #!/bin/bash
    
    #
    # grep_c_code
    #
    # Grep C files and print the results along with the function name and signature.
    # Requires: ctags, gawk, sed, bash, and you probably want grep too.
    #
    # Written by David Stav, December 19 2012.
    #
    # Released to the public domain.
    #
    
    if [ $# -lt 2 ]; then
        echo "Usage: $0 <grep_cmd> <files/dirs...>" >&2
        echo "" >&2
        echo "Example:" >&2
        echo "  $0 'grep --color=always -n -e \"PATTERN\"' file1 file2 dir1 dir2 | less -R" >&2
        exit 1
    fi
    
    GREP_CMD="$1"
    shift
    
    GAWK_SCRIPT="`
    sed -n -e '/^##### START of gawk script #####$/,/^##### END of gawk script #####$/p' \"$0\" | \
    sed -n -e '2,$ { $ D; p}'
    `"
    
    ctags -f - -R --sort=no -n --fields=+afikKmsSzt --extra=+fq "$@" | \
    gawk "$GAWK_SCRIPT" "$GREP_CMD" | \
    bash
    
    exit 0
    
    ##### START of gawk script #####
    function parse_line(a)
    {
        a["tagname"] = $1;
        a["filename"] = $2;
        a["line_number"] = gensub(/^([0-9]+).*$/, "\\1", 1, $3);
        if (a["line_number"] == $3)
        {
            a["line_number"] = "0";
        }
        a["kind"] = gensub(/^.*\tkind:([^\t]+).*$/, "\\1", 1, $0);
        if (a["kind"] == $0)
        {
            a["kind"] = "unknown kind";
        }
        a["signature"] = gensub(/^.*\tsignature:(.*)$/, "\\1", 1, $0);
        if (a["signature"] == $0)
        {
            a["signature"] = "";
        }
    }
    
    function grep_section(a, next_line_number)
    {
        printf("\n");
        printf("\n");
        printf("\n");
        printf("cat '%s' | \\\n", a["filename"]);
        printf("sed -n -e '%s,%sp' | \\\n", a["line_number"], next_line_number);
        printf("%s | \\\n", grep_cmd);
        printf("sed -e '1 i \\\n");
        printf("\\n\\n\\n--\\\n");
        printf("[%s:%s]\\\n", a["filename"], a["line_number"]);
        printf("<%s> %s%s\\\n", a["kind"], a["tagname"], a["signature"]);
        printf("'\n");
    }
    
    BEGIN \
    {
        FS = "\t";
        grep_cmd = ARGV[1];
        ARGV[1] = ""
    }
    
    !/^!/ \
    {
        parse_line(next_line);
        if (a["line_number"])
        {
            next_line_number = next_line["line_number"] - 1;
            grep_section(a, next_line_number);
            delete a;
        }
        for (key in next_line)
        {
            a[key] = next_line[key];
        }
    }
    
    END \
    {
        if (a["line_number"])
        {
            next_line_number = "$";
            grep_section(a, next_line_number);
        }
    }
    ##### END of gawk script #####
    

    Enjoy. :)

    0 讨论(0)
提交回复
热议问题