Làm thế nào để bạn chỉ tô màu một số từ khóa cho một tập lệnh bash?


10

Tôi đang chạy một số mã kiểm tra đơn vị. Mã kiểm tra đơn vị xuất văn bản thông thường. Có rất nhiều văn bản vì vậy tôi muốn làm nổi bật cho người dùng từ khóa quan trọng.

Trong trường hợp này, các từ khóa là "PASS" và "FAIL".

Làm thế nào để bạn tô màu "PASS" thành màu xanh lá cây và "FAIL" thành màu đỏ?


Bạn đã nghĩ về việc giảm tiêu chuẩn / stderr của các bài kiểm tra vượt qua và chỉ in ra thiết bị xuất chuẩn / thiết bị xuất chuẩn cho các bài kiểm tra thất bại? PHPUnit thực hiện điều này hoặc có thể cấu hình để thực hiện việc này. Tôi đã thấy rằng phương pháp này hoạt động khá tốt, YMMV.
Clayton Stanley

Câu trả lời:


8

supercat dường như làm những gì bạn đang tìm kiếm.

Gói: siêu xe
Mô tả-en: chương trình tô màu văn bản cho thiết bị đầu cuối và HTML
 Supercat là một chương trình tô màu văn bản dựa trên kết hợp thông thường
 biểu thức / chuỗi / ký tự. Supercat cũng hỗ trợ đầu ra html
 như văn bản ASCII tiêu chuẩn. Không giống như một số chương trình tô màu văn bản
 tồn tại, Supercat không yêu cầu bạn phải là một lập trình viên để
 làm quy tắc tô màu.
Trang chủ: http://supercat.nosredna.net/

Dường như không có cách nào để nói với nó những gì cần tô màu trên dòng lệnh, bạn phải chỉ định một tệp cấu hình.

Tôi dường như nhớ lại đã từng có một chương trình gọi là 'hilite' hoặc 'hl' làm nổi bật văn bản khớp với một mẫu (như grep --colour, nhưng cũng hiển thị các dòng không khớp), nhưng tôi không thể tìm thấy nó khi tôi tìm kiếm nó.

Cuối cùng, GNU grepcó thể được sử dụng để làm nổi bật các mẫu - nhưng chỉ có thể sử dụng một màu (nghĩa là bạn không thể có PASS màu xanh lá cây và FAIL màu đỏ, cả hai sẽ được tô sáng cùng màu).

Truyền dữ liệu của bạn thông qua một cái gì đó như thế này:

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

Ví dụ này sử dụng egrep (aka grep -E), nhưng -Gregrec cơ bản, -Fchuỗi cố định và -PPCRE cũng hoạt động.

Tất cả các trận đấu sẽ được làm nổi bật. Mặc định là màu đỏ hoặc đặt varP_COLOR env var.

Chìa khóa cho công việc này là phần cuối cùng |$trong mẫu khớp với dòng cuối (tức là tất cả các dòng khớp) để tất cả các dòng sẽ được hiển thị (nhưng không được tô màu).

Các \bđánh dấu ranh giới từ sao cho khớp với nó, ví dụ FAIL nhưng không FAILURE. chúng không cần thiết, vì vậy hãy loại bỏ chúng nếu bạn muốn ghép các từ một phần.

Đây là kịch bản trình bao bọc ví dụ cho supercat mà tôi đã viết ngày hôm qua. Nó hoạt động, nhưng bằng văn bản, tôi phát hiện ra rằng supercat không có bất kỳ tùy chọn nào cho các tìm kiếm không phân biệt chữ hoa chữ thường. IMO, điều đó làm cho chương trình ít hữu ích hơn đáng kể. Tuy nhiên, nó đã đơn giản hóa rất nhiều kịch bản vì tôi không phải viết tùy chọn '-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, nếu bạn đã sử dụng, supercatbạn có thể sửa đổi tập lệnh bạn đã đăng để tạo tệp cấu hình tạm thời dựa trên các đối số dòng lệnh, sau đó gọi spc -c /path/to/your/temp/config. Điều này sẽ cho phép bạn dễ dàng chỉ định các màu khác nhau cho các mẫu khác nhau trên dòng lệnh.
cas

cũng btw, tôi đã viết một kịch bản bao bọc đơn giản để làm điều đó. Tôi phải vào làm việc ngay bây giờ nhưng tôi sẽ dọn sạch nó, thêm một số bình luận, vv và đăng nó sau hôm nay.
cas

5

Đây là một kịch bản có mục đích chung để tô màu các mẫu biểu thức chính quy (có thể cần chỉnh sửa lại):

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

Đặt tên cho nó hilite.shvà sử dụng nó theo cách này:

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

Tôi đã làm điều này community wikibởi vì giải pháp của tôi không hoạt động.
Trevor Boyd Smith

Một cách dễ dàng để kiểm tra là tạo một tập lệnh khác lặp lại văn bản với các từ khóa "PASS" và "FAIL". Điều đó sau đó sẽ được gọi bởi kịch bản này.
Trevor Boyd Smith

Hơi lạc đề, nhưng tôi phải chỉ ra rằng phân tích cú pháp đầu ra $BINthông qua evalthay thế lệnh có lẽ rất mong manh, cồng kềnh và hết sức nguy hiểm. STDOUT là một luồng và thường được xử lý bằng luồng như các công cụ. Cố gắng nắm bắt toàn bộ một luồng trong một biến không hiệu quả lắm. Ngoài ra, evallà cực kỳ mạnh mẽ , vì vậy chỉ sử dụng nó nếu bạn thực sự biết những gì bạn đang làm.
jw013

Tôi đã thay thế kịch bản với một kịch bản làm việc.
angus

@angus, IMO kịch bản thực sự hay và ấn tượng.
Trevor Boyd Smith

3

Việc nhúng các chuỗi tùy ý (như tputđầu ra) vào các sedbiểu thức thay thế là có vấn đề vì bạn phải đảm bảo (bằng cách thoát) chuỗi là sedcú pháp hợp lệ , điều này phức tạp hơn nên tránh. Tôi sẽ sử dụng awkthay thế. Chỉ là một ví dụ:

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

Điều quan trọng là gán các tputchuỗi cho awkcác biến, được thực hiện ở đây bằng cách sử dụng các -vtùy chọn.


Tôi đã chạy chương trình của bạn và nó làm những gì cần thiết. Huzzah! Nhưng thật không may, tôi không phải là một bậc thầy awk vì vậy tôi thấy khó hiểu những gì đang xảy ra. Sửa tôi sai ở đâu. Đối với mỗi dòng mới awk được chạy? Vòng lặp for trong mã nguồn awk đang thực hiện: "cho tất cả các mã thông báo trong dòng"? sau đó nó xử lý từng mã thông báo?
Trevor Boyd Smith

Awk nghĩ về các lĩnh vực và hồ sơ. Theo mặc định, bản ghi là dòng văn bản và các trường không phải là khoảng trắng. Một awktập lệnh bao gồm một tập hợp các khối (thứ nằm giữa {}cấp cao nhất). Mỗi khối được liên kết với một điều kiện - trong bài viết của tôi ở trên không có vì tôi muốn hành động vô điều kiện trên mỗi dòng đầu vào. Awk hoạt động bằng cách đọc các bản ghi từ các tệp hoặc đầu vào tiêu chuẩn (trong trường hợp này là STDIN b / c không có tên tệp nào được cung cấp) và khớp chúng với mọi khối theo thứ tự, thực hiện khối trên bản ghi nếu điều kiện khớp.
jw013

2

sử dụng printf:

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

ví dụ.

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

cuối cùng \nthêm nhân vật dòng mới.

để xem các giá trị có thể của việc thử một cái gì đó như:

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

ngoài màu sắc, bạn có thể thêm các từ bổ nghĩa như in đậm hoặc gạch chân hoặc văn bản màu với nền màu bằng cách kết hợp các số. Để tạo văn bản màu xanh với nền màu xám được gạch chân và nổi bật thông qua sử dụng:

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

Chúc mừng

/ B2S


2

Nếu bạn vui lòng cài đặt tập lệnh BASH và ack, hhlightergói có màu mặc định hữu ích và giao diện dễ dàng https://github.com/paoloantinori/hhighlighter :

ví dụ cao

Bạn có thể sử dụng nó như vậy để làm nổi bật các hàng bắt đầu bằng FAIL:

h -i 'FAIL.*'

hoặc có chứa FAIL:

h -i '.*FAIL.*'

hoặc cho các mục nhật ký phổ biến khác nhau:

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

Và tất nhiên, đối với một màu duy nhất (màu đỏ) với grep trơn:

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

Các ^trận đấu phù hợp với mọi dòng, nhưng là một trình so khớp đặc biệt và in toàn bộ dòng. Biểu thức cần làm nổi bật được xác định sau a |. Các biểu thức khác có thể được thêm vào miễn là chúng được phân tách bằng |.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.