The script below can be used for static code analysis. It requires git, sed and grep {{{ # (c) Roel Kluin, 2009, GPL v2. #!/bin/bash # does git grep -n -E [options] "$(bli2 "[query]")", I'm too lazy for that. gg() { local opts; local q; local opts while [ $# -ne 0 ]; do [ "${1:0:2}" = "--" ] && break; if [ "${1:0:1}" = "-" ]; then opts="${opts:+$opts }${q:+$q }$1"; q="" else q="$1" fi shift; done git grep -n -E $opts "$(bli2 "$q")" $@ } # blank_it: replaces spaces with bracket expressions to match # optional/obligatory spaces for usage with egrep. bli2() { local l="$1" local int="[[:digit:]]" local hex="[[:xdigit:]]" local up_="[[:upper:]_]" local al_="[[:alpha:]_]" local AN_="[[:upper:][:digit:]_]" local an_="[[:alnum:]_]" local sp="[[:space:]]" local ns="[^[:space:]]" local V="$al_+$an_*" local em='!' # fixme: a regexp like [ * ]+ does not work (spaces on both sides) l="${l//@&...@/(&+\(-..\))*}" # 4 backrefs l="${l//@|...@/(\|+\(-..\))*}" # 4 backrefs l="${l//@&...&@/&+@...&@}" # 4 backrefs l="${l//@|...|@/\|+@...|@}" # 4 backrefs l="${l//@...&@/(\(-..\)&+)*}" # 4 backrefs l="${l//@...|@/(\(-..\)\|+)*}" # 4 backrefs l="${l//@&|...@/([&|]+\(-..\))*}" # 4 backrefs l="${l//@&|...&|@/[&|]+@...&|@}" # 4 backrefs l="${l//@...&|@/(\(-..\)[&|]+)*}" # 4 backrefs l="${l//\\\(-8.\\\)/[^()|&;]*(\(.8.\)[^()|&;]*)*}" # 9 backrefs l="${l//\\\(-..\\\)/[^()|&;]*(\(...\)[^()|&;]*)*}" # 3 backrefs l="${l//\\\(...\\\)/\([^();]*(\([^();]*(\([^();]*\)[^();]*)*\)[^();]*)*\)}" # 2 backrefs l="${l//\\\(.8.\\\)/\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*\)[^();]*)*\)[^();]*)*\)[^();]*)*\)[^();]*)\)[^();]*)*\)[^();]*)*\)[^();]*)*\)[^();]*)*\)}" # 8 backrefs l="${l//\\\[...\\\]/\[[^][]*(\[[^][]*(\[[^][]*\][^][]*)*\][^][]*)*\]}" # 2 backrefs l="${l//@V/$V}" l="${l//@Q2/[^[:alnum:]_>.]}" l="${l//@Q1/[^[[:alnum:]_.-]}" l="${l//@Q/[^[:alnum:]_]}" l="${l//@d/($int+[uUlLfF]?|$int+[uU]?[lL][lL]?|0x$hex+|$int+[lL][lL][uU]|$int*\.$int+[fF]?)}" l="${l//@K/$up_+$AN_*}" l="${l//@s/$sp*}" l="${l//@n/([^\n]*\n)*}" l="${l//@S/$sp+}" l="${l//\\$em/$em}" l="${l//@w/($V|\.$sp*|->$sp*|\[$sp*[^][]+$sp*\]|\($sp*[^)(]*$sp*\))+}" echo "$l" | sed -r " :a s/@branch/\(\\\\\{\.\.\.\\\\\}\|\[\^\{\};\]\*;\)/g # 3 backrefs s/@in_branch/\(\\\\\{\\\\\{-\.\.\\\\\}\)\?/g # 5 backrefs s/@branch8/\(\\\\\{\.8\.\\\\\}\|\[\^\{\};\]\*;\)/g # 9 backrefs s/\\\\\{-\.\.\\\\\}/\[^\}\{\]*\(\\\\\{...\\\\\}\[^\}\{\]*\)*/g # 4 backrefs s/\\\\\{-8\.\\\\\}/\[^\}\{\]*\(\\\\\{.8.\\\\\}\[^\}\{\]*\)*/g # 10 backrefs s/\\\\\{\.\.\.\\\\\}/\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}/g # 2 backrefs s/\\\\\{\.8\.\\\\\}/\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}/g # 9 backrefs s/($an_)$sp+($an_)/\1$sp+\2/g s/((^|[^\\\\])\[\^?([^][@]*|\[:[^][]+:\])*)($sp+)/\1@\4@/g s/([^@[:space:]]|^)$sp+/\1$sp*/g s/@($sp+)@/\1/g $!{ N ba } " } # echo a sed script to catch from multiline grep $n (where n=$#) and filter out $1 up to ${n-1}. # e.g. grep -E -n -H -B1 -A10 "foo" ~/file | sed -n -r "$(ecsed2 "foo.*bar" "foo")" # searches for lines with `foo', not followed by `bar' ecsed2() { local app not prt; local sp="[[:space:]]"; # space local Sp="[ $(echo -e "\t")]" local ns="[^[:space:]]"; # no space local bol="$ns*[:-][0-9]+[:-]" # begin of line local func="$(bli2 "$V\(...\)$Sp")" while [ $# -ne 1 ]; do if [ -n "$1" ]; then [ "${1:0:6}" = "--sed=" ] && not="${1:6}" || [ "${1:0:6}" = "--PrE=" ] && app="${1:6}" || [ "${1:0:6}" = "--PrT=" ] && prt="${1:6}" || not="$not /$(bli2 "$app$1")/d" fi shift done echo " /^--/b s/^($ns*)[:-]([0-9]+)[:-]/---[ vi \1 +\2 ]---\n/ :loop s/^$bol// /^(--$|\}$s|[^\n]*$func\n\{)/!{ /\/\//s/$Sp*\/\/.*$//g H \$!{ n b loop } } x /\/\*/s/$Sp*\/\*+([^*]*|\*[^\/])*\*+\/$Sp*/ /g /$(bli2 "$app$1")/!d $not p $prt d" } # gres does something like # git grep -E -n [-opts] "$(bli2 "$1")" -- '*.c' '*.h' | sed -n -r "$(ecsed2 "${@:2})" gres() { local opts gq sq eopts prt file; while [ $# -ne 0 ]; do [ "${1:0:1}" != "-" ] && break; [ "${1:0:6}" = "--PrE=" ] && gq="${1:6}" || [ "${1:0:6}" = "--PrT=" ] && prt="$1" || [ "${1:0:6}" = "--FiL=" ] && file="${1:6}" || [ "${1:0:6}" = "--sed=" ] && eopts="$1" || opts="${opts:+$opts }$1"; shift; done if [ -n "$file" ]; then sq="$(ecsed2 "$prt" "$eopts" "$@")" sed -n -r "$sq" "$file" elif [ -z "$gq" ]; then gq="$(bli2 "$1")"; sq="$(ecsed2 "$prt" "$eopts" "${@:2}")" else gq="$(bli2 "$gq")" sq="$(ecsed2 "$prt" "$eopts" "--PrE=$gq" "$@")"; fi git grep -E -n $opts "$gq" -- '*.c' '*.h' | sed -n -r "$sq" } }}} To use, save, e.g. as ~/bin/cvars.sh, and source it. For examples see examples on [wiki:roelkluin my page]