#!/bin/sh set -eu # variables # FROM= UNTIL= SED_ARGS= GREP_ARGS= GREPV_ARGS= # bin helpers # if STDBUF=$(which stdbuf); then STDBUF="$STDBUF -i0 -o0" fi PERL=$(which perl || true) if [ -n "$(sed 2>&1 | grep -- -u,)" ]; then SED="sed -u" else SED="${STDBUF:+$STDBUF }sed" fi GREP="${STDBUF:+$STDBUF }grep" # Colours # NORMAL="$(printf '\x1b[39;49m')" COLOUR="$NORMAL" RED="$(printf '\x1b[31m')" GREEN="$(printf '\x1b[32m')" YELLOW="$(printf '\x1b[33m')" BLUE="$(printf '\x1b[34m')" MAGENTA="$(printf '\x1b[35m')" CYAN="$(printf '\x1b[36m')" # shell helpers # die() { local arg0="$(basename "$0")" if [ $# -eq 0 ]; then sed -e "s!^!$arg0 :" else echo "$arg0: $@" fi >&2 exit 1 } cat <&2 # $PWD # $0 $* EOT # arguments # while [ $# -gt 0 ]; do case "${1:-}" in -f) # prefilter from FROM="$2" shift ;; -u) # prefilter until UNTIL="$2" shift ;; -e) # highlight pattern # if [ "$COLOUR" = "$RED" ]; then COLOUR="$GREEN" elif [ "$COLOUR" = "$GREEN" ]; then COLOUR="$MAGENTA" elif [ "$COLOUR" = "$MAGENTA" ]; then COLOUR="$YELLOW" elif [ "$COLOUR" = "$YELLOW" ]; then COLOUR="$CYAN" elif [ "$COLOUR" = "$CYAN" ]; then COLOUR="$BLUE" else COLOUR="$RED" fi case "$2" in "^"*"$") PATTERN="$2" ;; "^"*) PATTERN="$2.*" ;; *"$") PATTERN=".*$2" ;; *) PATTERN=".*$2.*" esac SED_ARGS="${SED_ARGS:+$SED_ARGS }-e 's!$PATTERN!$COLOUR\0$NORMAL!g'" shift ;; # simple grep options with arguments -C|-A|-B) GREP_ARGS="${GREP_ARGS:+$GREP_ARGS }$1 $2" shift ;; # grep options with merged arguments -C*|-A*|-B*) GREP_ARGS="${GREP_ARGS:+$GREP_ARGS }'$1'" ;; # complex grep options with arguments -E) GREP_ARGS="${GREP_ARGS:+$GREP_ARGS }$1 '$2'" shift ;; # -g is `grep -e` -g) GREP_ARGS="${GREP_ARGS:+$GREP_ARGS }-e '$2'" shift ;; # -v is `grep -v e` -v) GREPV_ARGS="${GREPV_ARGS:+$GREPV_ARGS }-e '$2'" shift ;; # simple grep options without arguments -i) GREP_ARGS="${GREP_ARGS:+$GREP_ARGS }$1" ;; --) shift break ;; # any other option -*) die "$1 unsupported" ;; # straight arguments *) break ;; esac shift done export LC_ALL=C # # compose pipeline # PIPELINE= # GREP -v FILTER if [ -n "${GREPV_ARGS:-}" ]; then PIPELINE="${PIPELINE:+$PIPELINE | }$GREP -a -v $GREPV_ARGS" fi # FROM/UNTIL FILTER if [ -z "${FROM:-}${UNTIL:-}" ]; then : elif [ -x "$PERL" ]; then prg= if [ -n "$FROM" ]; then prg="print if \$print; \$print ||= /$FROM/;" else prg="print;" fi [ -z "$UNTIL" ] || prg="last if /$UNTIL/; $prg" PIPELINE="${PIPELINE:+$PIPELINE | }$PERL -lne '$prg'" else PIPELINE="${PIPELINE:+$PIPELINE | }$SED" [ -z "${FROM:-}" ] || PIPELINE="$PIPELINE -e '0,/$FROM/d'" [ -z "${UNTIL:-}" ] || PIPELINE="$PIPELINE -e '/$UNTIL/,\$d'" # no grep? combine both sed calls if [ -z "${GREP_ARGS:-}" -a -n "${SED_ARGS:-}" ]; then PIPELINE="$PIPELINE $SED_ARGS" SED_ARGS= fi fi # GREP FILTER if [ -n "${GREP_ARGS:-}" ]; then PIPELINE="${PIPELINE:+$PIPELINE | }$GREP -a $GREP_ARGS" fi # HIGHLIGHT if [ -n "${SED_ARGS:-}" ]; then PIPELINE="${PIPELINE:+$PIPELINE | }$SED $SED_ARGS" fi #and run if [ $# -eq 0 ]; then eval "${PIPELINE:-cat}" elif [ -n "$PIPELINE" ]; then "$@" | $PIPELINE else "$@" fi