Jak pokolorujesz tylko niektóre słowa kluczowe dla skryptu bash?

10

Korzystam z kodu testu jednostkowego. Kod testu jednostkowego wyświetla zwykły tekst. Jest dużo tekstu, więc chcę podkreślić ważne słowa kluczowe dla użytkownika.

W tym przypadku słowami kluczowymi są „PASS” i „FAIL”.

Jak koloryzujesz „PASS”, aby był zielony, a „FAIL”, aby był czerwony?

Trevor Boyd Smith
źródło
Czy zastanawiałeś się nad pominięciem standardowego testu (stderr) testów, które pomyślnie przejdą, i wydrukowaniem standardowego testu standardowego / standardowego testu dla testów zakończonych niepowodzeniem? PHPUnit to robi lub można to skonfigurować. Przekonałem się, że to podejście działa całkiem dobrze, YMMV.
Clayton Stanley,

Odpowiedzi:

8

supercat wydaje się robić to, czego szukasz.

Opakowanie: supercat
Description-pl: program, który koloryzuje tekst dla terminali i HTML
 Supercat to program, który koloryzuje tekst na podstawie regularnego dopasowywania
 wyrażenia / ciągi / znaki. Supercat obsługuje również wyjście HTML
 jako standardowy tekst ASCII. W przeciwieństwie do niektórych programów do kolorowania tekstu, które
 istnieje, Supercat nie wymaga bycia programistą
 ustal zasady kolorowania.
Strona główna: http://supercat.nosredna.net/

Wydaje się, że nie ma sposobu, aby powiedzieć mu, co ma być kolorowane w wierszu poleceń, musisz określić plik konfiguracyjny.

Wydaje mi się, że pamiętam, że kiedyś istniał program o nazwie „hilite” lub „hl”, który wyróżniał tekst pasujący do wzorca (na przykład grep --colour, ale wyświetlał również niepasujące linie), ale nie mogłem go znaleźć, gdy go szukałem.

Wreszcie, GNU grepmoże być użyte do podświetlenia wzorów - ale można użyć tylko jednego koloru (tzn. Nie możesz mieć PASS w kolorze zielonym i FAIL w kolorze czerwonym, oba byłyby podświetlone tym samym kolorem).

Przeprowadź dane przez coś takiego:

egrep --color "\b(PASS|FAIL)\b|$"

W tym przykładzie użyto egrep (aka grep -E), ale działają również -Gpodstawowe wyrażenia regularne, -Ffixed-string i -PPCRE.

Wszystkie mecze zostaną podświetlone. Domyślnie jest czerwony lub ustaw zmienną GREP_COLOR env var.

Kluczem do tego jest to, że finał |$we wzorze pasuje do końca linii (tzn. Wszystkie linie pasują), więc wszystkie linie będą wyświetlane (ale nie pokolorowane).

\bto znaczniki granicy słowa, dzięki czemu pasują np. FAIL, ale nie FAILURE. nie są konieczne, więc usuń je, jeśli chcesz dopasować częściowe słowa.

Oto przykładowy skrypt otoki dla superkata, który napisałem wczoraj. Działa, ale pisząc to odkryłem, że supercat nie ma żadnej opcji wyszukiwania bez rozróżniania wielkości liter. IMO, dzięki czemu program jest znacznie mniej przydatny. To jednak znacznie uprościło skrypt, ponieważ nie musiałem pisać opcji „-i” :)

#! /bin/bash 

# Requires: tempfile from debian-utils, getopt from util-linux, and supercat

SCRIPTNAME=$(basename $0)
CFGFILE=$(tempfile -p spc)

usage() {
  cat <<__EOF__
Highlight regexp patterns found on stdin or files specified on command
line with specified colours.

Usage: $SCRIPTNAME [ --colour "pattern" ...] [FILE]

Options:

        -k,--black   regexp
        -r,--red     regexp
        -g,--green   regexp
        -y,--yellow  regexp
        -b,--blue    regexp
        -m,--magenta regexp
        -c,--cyan    regexp
        -w,--white   regexp

Example:

    run-script.sh | $SCRIPTNAME --green PASS --red FAIL

__EOF__
  exit 0
}


# Format definition from the spc man page:
#1234567890123456789012345678901234567890123456789012345
#HTML Color Name      Col A N T RE / String / Characters
FMT="%-20s %3s %1s %1s %1s (%s)\n"

add_color_to_config() {
  COLOR="$1"
  PATTERN="$2"

  printf "$FMT" "$COLOR" "$COLOR" - 0 r "$PATTERN" >> "$CFGFILE"
}


# uses the "getopt" program from util-linux, which supports long
# options. The "getopts" built-in to bash does not.
TEMP=$(getopt \
       -o 'hk:r:g:y:b:m:c:w:' \
       -l 'help,black:,red:,green:,yellow:,blue:,magenta:,cyan:,white:' \
       -n "$0" -- "$@")

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

eval set -- "$TEMP"

while true ; do
    case "$1" in
        -k|--bla*)       add_color_to_config blk "$2" ; shift 2 ;;
        -r|--red)        add_color_to_config red "$2" ; shift 2 ;;
        -g|--gre*)       add_color_to_config grn "$2" ; shift 2 ;;
        -y|--yel*)       add_color_to_config yel "$2" ; shift 2 ;;
        -b|--blu*)       add_color_to_config blu "$2" ; shift 2 ;;
        -m|--mag*)       add_color_to_config mag "$2" ; shift 2 ;;
        -c|--cya*)       add_color_to_config cya "$2" ; shift 2 ;;
        -w|--whi*)       add_color_to_config whi "$2" ; shift 2 ;;

        -h|--hel*)       usage ; exit 0 ;;

        --)         shift ; break ;;

        *)          echo 'Unknown option!' ; exit 1 ;;
    esac
done

spc -R -c "$CFGFILE" "$@"
rm -f "$CFGFILE"
cas
źródło
1
BTW, jeśli użyłeś, supercatmożesz zmodyfikować opublikowany skrypt, aby wygenerować tymczasowy plik konfiguracyjny na podstawie argumentów wiersza poleceń, a następnie wywołać spc -c /path/to/your/temp/config. Umożliwi to łatwe określenie różnych kolorów dla różnych wzorów w wierszu poleceń.
cas
również btw, napisałem prosty skrypt otoki, aby to zrobić. Muszę teraz iść do pracy, ale posprzątam, dodam komentarze itp. i opublikuję później.
cas
5

Oto skrypt ogólnego przeznaczenia do kolorowania wzorów wyrażeń regularnych (prawdopodobnie wymaga retuszu):

#! /bin/bash

color_to_num () {
  case $1 in
    black)  echo 0;;
    red)    echo 1;;
    green)  echo 2;;
    yellow) echo 3;;
    blue)   echo 4;;
    purple) echo 5;;
    cyan)   echo 6;;
    white)  echo 7;;
    *)      echo 0;;
  esac
}

# default values for foreground and background colors
bg=
fg=
bold="$(tput bold)"
italics=""
boundary=""

while getopts f:b:sli option; do
  case "$option" in
    f) fg="$OPTARG";;
    b) bg="$OPTARG";;
    s) bold="";;
    l) boundary=".*";;
    i) italics="$(tput sitm)";;
  esac
done

shift $(($OPTIND - 1))

pattern="$*"

if [ -n "$fg" ]; then
  fg=$(tput setaf $(color_to_num $fg))
fi
if [ -n "$bg" ]; then
  bg=$(tput setab $(color_to_num $bg))
fi

if [ -z "$fg$bg" ]; then
  fg=$(tput smso)
fi

sed "s/${boundary}${pattern}${boundary}/${bold}${italics}${fg}${bg}&$(tput sgr0)/g"

Nazwij go hilite.shi użyj w ten sposób:

$ ./BIN_PROGRAM | hilite.sh -f green PASS | hilite.sh -f red FAIL

$ # Here is an example one liner
$ echo -e "line 1: PASS\nline 2: FAIL" | hilite.sh -f green PASS | hilite.sh -f red FAIL
Trevor Boyd Smith
źródło
Zrobiłem to, community wikiponieważ moje rozwiązanie nie działa.
Trevor Boyd Smith
Łatwym sposobem na przetestowanie jest utworzenie kolejnego skryptu, który wyśle ​​echo tekstu ze słowami kluczowymi „PASS” i „FAIL”. To byłoby następnie wywoływane przez ten skrypt.
Trevor Boyd Smith
Lekko off topic, ale muszę podkreślić, że podczas analizowania danych wyjściowych $BINpoprzez evaldo podstawienia polecenia jest prawdopodobnie krucha, kłopotliwe, a wręcz niebezpieczne. STDOUT jest strumieniem i ogólnie ma być przetwarzany przez narzędzia podobne do strumienia. Próba przechwycenia całego strumienia w zmiennej nie jest zbyt wydajna. Ponadto evaljest niebezpiecznie potężny , więc używaj go tylko wtedy, gdy naprawdę wiesz, co robisz.
jw013,
Zastąpiłem skrypt działającym.
angus
@angus, naprawdę naprawdę dobry i imponujący skrypt IMO.
Trevor Boyd Smith
3

Osadzanie dowolnych ciągów (takich jak tputdane wyjściowe) w sedwyrażeniach zamieniających jest problematyczne, ponieważ musisz upewnić się (poprzez ucieczkę), że jest ona poprawna sedskładnia, co jest bardziej złożone, czego najlepiej unikać. Użyłbym awkzamiast tego. Jako przykład:

{ echo line 1: PASS; echo line 2: FAIL; } | 
    awk -v "red=$(tput setaf 1)" -v "green=$(tput setaf 2)" \
        -v "reset=$(tput sgr0)" '
    { for (i = 1; i <= NF; i++) {
           if ($i == "FAIL") printf "%s", red "FAIL" reset;
           else if ($i == "PASS") printf "%s", green "PASS" reset;
           else printf "%s", $i

           if (i == NF) printf "%s", ORS
           else printf "%s", OFS 
      }}'

Kluczem jest przypisanie tputsekwencji do awkzmiennych, wykonanych tutaj przy użyciu -vopcji.

jw013
źródło
Uruchomiłem twój program i robi to, co jest potrzebne. Huzzah! Ale niestety nie jestem guru awk, więc trudno mi zrozumieć, co się dzieje. Popraw mnie tam, gdzie się mylę. Dla każdej nowej linii uruchamiany jest awk? Pętla for w kodzie źródłowym awk robi: „dla wszystkich tokenów w linii”? następnie przetwarza każdy token?
Trevor Boyd Smith
Awk myśli w kategoriach pól i zapisów. Domyślnie rekordy są wierszami tekstu, a pola nie są spacjami. awkSkrypt składa się z zestawu klocków (rzeczy między {}na poziomie górnym). Każdy blok jest powiązany z warunkiem - w moim poście powyżej nie ma takiego, ponieważ chcę bezwarunkowo działać na każdej linii wejściowej. Awk działa poprzez odczytywanie rekordów z plików lub standardowe wejście (w tym przypadku jest to STDIN b / c nie podano nazw plików) i dopasowanie ich do każdego bloku w kolejności, wykonując blok na rekordzie, jeśli warunek jest zgodny.
jw013,
2

użyj printf:

printf "\e[%sm%s\e[00m\n" <some_number> <text_in_colour>

na przykład.

printf "\e[%sm%s\e[00m\n" 32 yodle

ostatni \ndodaje znak nowej linii.

aby zobaczyć możliwe wartości, spróbuj czegoś takiego:

for i in {0..9} {30..38} {90..98} {100..108};
do
    printf "%d:\e[%sm%s\e[00m\n" $i "$i" yodle;
done

oprócz koloru można dodawać modyfikatory, takie jak pogrubienie, podkreślenie lub kolorowy tekst z kolorowym tłem, łącząc liczby. Aby utworzyć niebieski tekst z szarym tłem, które jest podkreślone i przekreślone poprzez użycie:

printf "\e[%sm%s\e[00m\n" "4;9;34;107" yodle

Twoje zdrowie,

/ B2S

Born2Smile
źródło
2

Jeśli z przyjemnością zainstalujesz skrypt BASH ack, a hhlighterpakiet ma przydatne domyślne kolory i prosty interfejs https://github.com/paoloantinori/hhighlighter :

przykład hhighlight

Możesz go użyć w taki sposób, aby podświetlić wiersze rozpoczynające się od FAIL:

h -i 'FAIL.*'

lub które zawierają FAIL:

h -i '.*FAIL.*'

lub dla różnych wspólnych wpisów w dzienniku:

h -i '.*FAIL.*' '.*PASS.*' '.*WARN.*'

I oczywiście dla jednego koloru (czerwonego) z prostym grepem:

$ printf 'Pass: good job\nFail: bad job\n' | grep -Ei --colour=auto '^|fail.*'

^Pasuje do każdego wiersza, ale jest specjalny układ dopasowujący i drukuje całą linię. Wyrażenie, które należy wyróżnić, jest zdefiniowane po |. Można dodawać kolejne wyrażenia, o ile są one oddzielone |.

Andy
źródło