Як ви забарвлюєте лише деякі ключові слова для скрипта bash?


10

Я виконую деякий код тесту одиниці. Тестовий код одиниці виводить звичайний текст. Тексту дуже багато, тому я хочу виділити для користувача важливі ключові слова.

У цьому випадку ключові слова "PASS" і "FAIL".

Як забарвити "PASS" зеленим кольором, а "FAIL" - червоним?


Чи задумувались ви про те, щоб придушити stdout / stderr тестів, які проходять, і лише надрукувати stdout / stderr за невдалі тести? PHPUnit робить це, або налаштовується для цього. Я виявив, що такий підхід працює досить добре, YMMV.
Клейтон Стенлі

Відповіді:


8

supercat здається, робиш те, що ти шукаєш.

Упаковка: суперката
Description-en: програма, яка забарвлює текст для терміналів та HTML
 Supercat - це програма, яка розфарбовує текст на основі відповідності звичайному
 вирази / рядки / символи. Supercat також підтримує вихід HTML
 як стандартний текст ASCII. На відміну від деяких програм, що забарвлюють текст, які
 існує, Supercat не вимагає від вас бути програмістом
 скласти правила колоризації.
Домашня сторінка: http://supercat.nosredna.net/

Здається, немає ніякого способу сказати, що слід розфарбувати в командному рядку, ви повинні вказати файл конфігурації.

Здається, я пам'ятаю, що раніше була програма під назвою "hilite" або "hl", яка виділяла текст, який відповідав шаблону (наприклад grep --colour, але відображав також невідповідні рядки), але я не міг його знайти, коли шукав його.

Нарешті, GNU grepможна використовувати для виділення візерунків - але можна використовувати лише один колір (тобто ви не можете мати PASS в зеленому та FAIL в червоному, обидва будуть виділятися одним кольором).

Проведіть свої дані через щось подібне:

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

У цьому прикладі використовується egrep (aka grep -E), але також працюють -Gбазові регулярні вирази, -Fфіксований рядок та -PPCRE.

Усі матчі будуть виділені. За замовчуванням - червоний або встановіть GREP_COLOR env var.

Ключовим у цій роботі є те, що фінал |$у шаблоні відповідає кінцевому рядку (тобто всі рядки збігаються), тому всі рядки будуть відображатися (але не кольоровими).

Вони \bє граничними маркерами слова, щоб вони відповідали, наприклад, FAIL, але не FAILURE. вони не потрібні, тому видаліть їх, якщо ви хочете відповідати частковим словам.

Ось приклад сценарію обгортки для суперката, який я написав вчора. Це працює, але, пишучи це, я виявив, що суперката не має жодного варіанту для нечутливих до регістру пошуків. IMO, що робить програму значно менш корисною. Однак це значно спростило сценарій, оскільки мені не довелося писати варіант '-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"

1
BTW, якщо ви використовували, supercatви можете змінити опублікований сценарій для створення тимчасового конфігураційного файла на основі аргументів командного рядка, а потім зателефонувати spc -c /path/to/your/temp/config. Це дозволить вам легко вказати різні кольори для різних візерунків у командному рядку.
cas

також btw, я написав простий скрипт для обгортки для цього. я маю взяти участь у роботі зараз, але я очищу його, додаю деякі коментарі тощо та опублікую це пізніше сьогодні.
cas

5

Ось скрипт загального призначення для розфарбування шаблонів регулярних виразів (мабуть, потребує певної ретуші)

#! /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"

Назвіть це ім’я hilite.shта використовуйте його так:

$ ./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

Я зробив це, community wikiтому що моє рішення не працює.
Тревор Бойд Сміт

Найпростіший спосіб перевірити - скласти ще один сценарій, який повторює текст із ключовими словами "ПАС" та "НЕВІДОМ". Тоді цей сценарій буде названий.
Тревор Бойд Сміт

Трохи поза темою, але я мушу зазначити, що аналіз результатів $BINчерез evalзаміну команд, ймовірно, крихкий, громіздкий і прямо небезпечний. STDOUT - це потік, який, як правило, має оброблятися потоковими інструментами. Спроба захопити весь потік у змінній не дуже ефективно. Також evalнебезпечно потужний , тому використовуйте його лише тоді, коли ви дійсно знаєте, що робите.
jw013

Я замінив сценарій робочим.
ангус

@angus, дійсно дуже хороший і вражаючий сценарій IMO.
Тревор Бойд Сміт

3

Вбудовувати довільні рядки (наприклад, tputвихідні) в sedзаміни виразів проблематично, тому що ви повинні забезпечити (уникнувши) рядок дійсним sedсинтаксисом, що є більшою складністю, якої найкраще уникати. Я б використав awkзамість цього. Як приклад:

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

Ключ полягає в призначенні tputпослідовностей awkзмінним, що робиться тут, використовуючи -vпараметри.


Я запустив вашу програму, і вона робить все, що потрібно. Huzzah! Але, на жаль, я не будний гуру, тому мені важко зрозуміти, що відбувається. Виправте мене там, де я помиляюся. Для кожного нового рядка запущено awk? Цикл for у вихідному коді awk робить: "для всіх маркерів у рядку"? то він обробляє кожен маркер?
Тревор Бойд Сміт

Awk думає з точки зору полів і записів. За замовчуванням записи - це рядки тексту, а поля - це непробільний простір. awkСценарій складається з набору блоків (матеріал між {}на рівні верхнього). Кожен блок асоціюється з умовою - в моєму дописі вище цього немає, тому що я хочу беззастережно діяти на кожному вхідному рядку. Awk працює, зчитуючи записи з файлів або стандартного вводу (у цьому випадку це STDIN b / c, імена файлів не були надані), і порівнюючи їх з кожним блоком у порядку, виконуючи блок запису, якщо умова відповідає.
jw013

2

використовувати printf:

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

напр.

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

останній \nдодає символу нового рядка.

щоб побачити можливі значення спробувати щось на кшталт:

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

окрім кольору, ви можете додавати модифікатори, такі як жирний або підкреслений, або кольоровий текст із кольоровим фоном, комбінуючи цифри. Щоб створити синій текст із сірим фоном, який підкреслено та накреслено за допомогою використання:

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

Ура,

/ B2S


2

Якщо ви раді встановити сценарій BASH і ack, hhlighterпакет має корисні кольори за замовчуванням та простий інтерфейс https://github.com/paoloantinori/hhighlighter :

Приклад hhighlight

Ви можете використовувати його так, щоб виділити рядки, які починаються з FAIL:

h -i 'FAIL.*'

або які містять FAIL:

h -i '.*FAIL.*'

або для різних загальних записів журналу:

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

І звичайно, для одного кольору (червоного) з простим грепом:

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

^Відповідає кожному рядку, але це особливі узгодження і виводить всю рядок. Вираз, який слід виділити, визначається після a |. Подальші вирази можна додавати до тих пір, поки вони розділені |.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.