bảng màu setput? Làm thế nào để xác định mã màu?


79

Tôi đang trong quá trình tô màu thiết bị đầu cuối của tôi PS1.

Tôi đang thiết lập các biến màu bằng cách sử dụng tput; ví dụ: đây là màu tím:

PURPLE=$(tput setaf 125)

Câu hỏi:

Làm cách nào để tìm mã màu (ví dụ 125) của các màu khác?

Có một bảng hướng dẫn màu / bảng cheat ở đâu đó?

Tôi chỉ không chắc chắn đó 125là gì Có cách nào để lấy màu hex và chuyển đổi thành số setafcó thể sử dụng không?


Câu trả lời:


153

Số lượng màu có sẵn để tham số được đưa ra bởi tput colors.

Để xem 8 màu cơ bản (như được sử dụng setftrong thiết bị đầu cuối urxvt và setaftrong thiết bị đầu cuối xterm):

$ printf '\e[%sm▒' {30..37} 0; echo           ### foreground
$ printf '\e[%sm ' {40..47} 0; echo           ### background

Và thường được đặt tên như thế này:

Color       #define       Value       RGB
black     COLOR_BLACK       0     0, 0, 0
red       COLOR_RED         1     max,0,0
green     COLOR_GREEN       2     0,max,0
yellow    COLOR_YELLOW      3     max,max,0
blue      COLOR_BLUE        4     0,0,max
magenta   COLOR_MAGENTA     5     max,0,max
cyan      COLOR_CYAN        6     0,max,max
white     COLOR_WHITE       7     max,max,max

Để xem 256 màu mở rộng (như được sử dụng setaftrong urxvt):

$ printf '\e[48;5;%dm ' {0..255}; printf '\e[0m \n'

Nếu bạn muốn số và một đầu ra có thứ tự:

#!/bin/bash
color(){
    for c; do
        printf '\e[48;5;%dm%03d' $c $c
    done
    printf '\e[0m \n'
}

IFS=$' \t\n'
color {0..15}
for ((i=0;i<6;i++)); do
    color $(seq $((i*36+16)) $((i*36+51)))
done
color {232..255}

Biểu đồ 256 màu theo thứ tự, được dán nhãn bằng chỉ mục của chúng


16 triệu màu cần khá nhiều mã (một số bảng điều khiển không thể hiển thị điều này).
Những điều cơ bản là:

fb=3;r=255;g=1;b=1;printf '\e[0;%s8;2;%s;%s;%sm▒▒▒ ' "$fb" "$r" "$g" "$b"

fbfront/backhoặc 3/4.

Một bài kiểm tra đơn giản về khả năng điều khiển của bạn để thể hiện rất nhiều màu sắc là:

for r in {200..255..5}; do fb=4;g=1;b=1;printf '\e[0;%s8;2;%s;%s;%sm   ' "$fb" "$r" "$g" "$b"; done; echo

đường màu đỏ, mờ dần từ đậm hơn sang nhạt hơn (từ trái sang phải) Nó sẽ hiển thị một đường màu đỏ với một sự thay đổi rất nhỏ trong tông màu từ trái sang phải. Nếu có thể nhìn thấy thay đổi nhỏ đó, bảng điều khiển của bạn có khả năng 16 triệu màu.

Mỗi r, gblà một giá trị từ 0 đến 255 cho RGB (Đỏ, Xanh lục, Xanh lam).

Nếu loại bảng điều khiển của bạn hỗ trợ điều này, mã này sẽ tạo một bảng màu:

mode2header(){
    #### For 16 Million colors use \e[0;38;2;R;G;Bm each RGB is {0..255}
    printf '\e[mR\n' # reset the colors.
    printf '\n\e[m%59s\n' "Some samples of colors for r;g;b. Each one may be 000..255"
    printf '\e[m%59s\n'   "for the ansi option: \e[0;38;2;r;g;bm or \e[0;48;2;r;g;bm :"
}
mode2colors(){
    # foreground or background (only 3 or 4 are accepted)
    local fb="$1"
    [[ $fb != 3 ]] && fb=4
    local samples=(0 63 127 191 255)
    for         r in "${samples[@]}"; do
        for     g in "${samples[@]}"; do
            for b in "${samples[@]}"; do
                printf '\e[0;%s8;2;%s;%s;%sm%03d;%03d;%03d ' "$fb" "$r" "$g" "$b" "$r" "$g" "$b"
            done; printf '\e[m\n'
        done; printf '\e[m'
    done; printf '\e[mReset\n'
}
mode2header
mode2colors 3
mode2colors 4

biểu đồ màu nền trước mẫu với chỉ mục của chúng là nhãn

biểu đồ màu nền mẫu với chỉ số của chúng là nhãn

Để chuyển đổi giá trị màu hex thành chỉ mục màu 0-255 (gần nhất):

fromhex(){
    hex=${1#"#"}
    r=$(printf '0x%0.2s' "$hex")
    g=$(printf '0x%0.2s' ${hex#??})
    b=$(printf '0x%0.2s' ${hex#????})
    printf '%03d' "$(( (r<75?0:(r-35)/40)*6*6 + 
                       (g<75?0:(g-35)/40)*6   +
                       (b<75?0:(b-35)/40)     + 16 ))"
}

Sử dụng nó như:

$ fromhex 00fc7b
048
$ fromhex #00fc7b
048

Để tìm số màu như được sử dụng trong định dạng màu HTML :

#!/bin/dash
tohex(){
    dec=$(($1%256))   ### input must be a number in range 0-255.
    if [ "$dec" -lt "16" ]; then
        bas=$(( dec%16 ))
        mul=128
        [ "$bas" -eq "7" ] && mul=192
        [ "$bas" -eq "8" ] && bas=7
        [ "$bas" -gt "8" ] && mul=255
        a="$((  (bas&1)    *mul ))"
        b="$(( ((bas&2)>>1)*mul ))" 
        c="$(( ((bas&4)>>2)*mul ))"
        printf 'dec= %3s basic= #%02x%02x%02x\n' "$dec" "$a" "$b" "$c"
    elif [ "$dec" -gt 15 ] && [ "$dec" -lt 232 ]; then
        b=$(( (dec-16)%6  )); b=$(( b==0?0: b*40 + 55 ))
        g=$(( (dec-16)/6%6)); g=$(( g==0?0: g*40 + 55 ))
        r=$(( (dec-16)/36 )); r=$(( r==0?0: r*40 + 55 ))
        printf 'dec= %3s color= #%02x%02x%02x\n' "$dec" "$r" "$g" "$b"
    else
        gray=$(( (dec-232)*10+8 ))
        printf 'dec= %3s  gray= #%02x%02x%02x\n' "$dec" "$gray" "$gray" "$gray"
    fi
}

for i in $(seq 0 255); do
    tohex ${i}
done

Sử dụng nó làm ("cơ bản" là 16 màu đầu tiên, "màu" là nhóm chính, "màu xám" là màu xám cuối cùng):

$ tohex 125                  ### A number in range 0-255
dec= 125 color= #af005f
$ tohex 6
dec=   6 basic= #008080
$ tohex 235
dec= 235  gray= #262626

Chức năng fromhex của bạn là tuyệt vời! Cám ơn rất nhiều!
mhulse

Lovin' fromhex. Cảm ơn một lần nữa! Ngoài ra, tôi đã thêm một kiểm tra cho# . Phản hồi?
mhulse

1
Có, loại bỏ một '#' hàng đầu là một sự bảo vệ hợp lý. Tôi thấy đơn giản hơn nhiều để sử dụng hex=${1#"#"}. Nó sẽ xóa không có gì nếu $1không có a #và xóa nó nếu nó tồn tại. Xem mã cập nhật của tôi.

Đẹp! Nhỏ gọn hơn nhiều. Cập nhật mã của tôi bây giờ. Cảm ơn bạn!!!!
mhulse

Lưu ý rằng ít nhất trong phiên bản xterm của \e[0;%s8;2;%s;%s;%smtôi, tôi không cung cấp cho tôi 16 triệu màu, chỉ là màu trong bảng màu 240 gần nhất với rgb được yêu cầu.
Stéphane Chazelas

14

Câu trả lời ngắn gọn là bạn có thể tìm thấy trên các bảng màu web và kết hợp chúng với số màu.

Câu trả lời dài là ánh xạ chính xác phụ thuộc vào thiết bị đầu cuối -

Đây 125là một tham số cho một chuỗi thoát được gọi là setaftrong mô tả thiết bị đầu cuối. tputkhông có ý nghĩa cụ thể với số. Điều đó thực sự phụ thuộc vào trình giả lập thiết bị đầu cuối cụ thể.

Một thời gian trước, ANSI đã xác định mã cho 8 màu và có hai sơ đồ để đánh số chúng. Cả hai được nhìn thấy trong một số mô tả thiết bị đầu cuối như các cặp setf/setbhoặc setaf/setab. Vì cái sau có ý nghĩa "màu ANSI", bạn sẽ thấy nó được sử dụng thường xuyên hơn. Cái trước (setf / setb) đã chuyển thứ tự cho màu đỏ / xanh như được ghi chú trong các câu hỏi thường gặp Tại sao màu đỏ / màu xanh lại thay thế cho nhau? , nhưng trong cả hai trường hợp, lược đồ được thiết lập chỉ để đánh số màu. Không có mối quan hệ được xác định trước giữa các số đó và nội dung RGB.

Đối với các trình giả lập thiết bị đầu cuối cụ thể, có các bảng màu được xác định trước có thể được liệt kê đủ dễ dàng - và có thể được lập trình bằng cách sử dụng các chuỗi thoát này. Không tiêu chuẩn liên quan và bạn sẽ thấy sự khác biệt giữa các trình giả lập thiết bị đầu cuối, như đã lưu ý trong Câu hỏi thường gặp về xterm Tôi không thích màu xanh lam đó .

Tuy nhiên, quy ước thường bị nhầm lẫn với các tiêu chuẩn. Trong sự phát triển của xterm trong 20 năm qua, nó đã kết hợp các màu ANSI (8), điều chỉnh các aixtermtính năng (16) màu, thêm các tiện ích mở rộng cho 88 và 256 màu. Phần lớn trong số đó đã được các nhà phát triển khác áp dụng cho các trình giả lập thiết bị đầu cuối khác nhau. Điều đó được tóm tắt trong Câu hỏi thường gặp về xterm Tại sao không tạo "xterm" tương đương với "xterm-256color"? .

Mã nguồn xterm bao gồm các tập lệnh để thể hiện màu sắc, ví dụ, sử dụng các chuỗi thoát tương tự tputsẽ sử dụng.

Bạn cũng có thể thấy câu hỏi / câu trả lời này hữu ích: Giá trị RGB của các màu trong chỉ số màu mở rộng Ansi (17-255)


Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn Thomas, tôi thực sự đánh giá cao nó! Tôi đang dùng Mac / OS X chạy iTerm. Giải thích của bạn thực sự giúp tôi hiểu thêm về thiết lập của mình (Tôi đã thực hiện rất nhiều bản sao / dán từ nhiều màu sắc khác nhau của người khác trên web). Tôi thực sự đánh giá cao bạn đã dành thời gian để viết cho tôi một câu trả lời chi tiết và nhiều thông tin. :)
mhulse

9

Các tputtiện ích được sử dụng một bảng tra cứu 256-màu để in chuỗi ANSI thoát 8-bit (bắt đầu với Esc[) mà làm cho sử dụng khả năng thiết bị đầu cuối , do đó, những trình tự điều khiển có thể được giải thích như màu sắc. Đây là bộ 256 màu được xác định trước được sử dụng phổ biến trên các card đồ họa.

Để in tất cả 256 màu trong thiết bị đầu cuối, hãy thử một lớp lót sau:

for c in {0..255}; do tput setaf $c; tput setaf $c | cat -v; echo =$c; done

Gợi ý: Nối | columnvào danh sách cột.

Bảng tra cứu 256 màu này cũng có thể được tìm thấy tại trang Wikipedia như sau:

Đồ thị;  Mã thoát ANSI;  Bảng tra cứu 8 bit 256 màu tại Wikipedia;  Chế độ 256 màu - nền trước: ESC [38; 5; #m nền: ESC [48; 5; #m


3

Với zsh và trong một xtermthiết bị đầu cuối giống như ( xtermvà các vtethiết bị đầu cuối dựa trên gnome-terminal, như xfce4-terminal... ít nhất), bạn có thể làm:

$ read -s -t1 -d $'\a' $'c?\e]4;125;?\a' && echo "${c##*;}"
rgb:afaf/0000/5f5f

Tương đương bash:

read -s -t1 -d $'\a' -p $'\e]4;125;?\a' c && echo "${c##*;}"

(bạn muốn dãy thoát để truy vấn màu sắc được gửi sau khi kỷ luật terminal echobị vô hiệu hóa (với -s) nếu không thì câu trả lời sẽ được hiển thị bằng nửa kỷ luật dòng thời gian, do đó việc gửi nó như một phần của readcửa sổ ( var?prompttrong zsh như trong ksh, -p prompttrong bash)).

để có được định nghĩa của màu 125 (ở đây là thông số RGB, mỗi số là cường độ của các thành phần Đỏ, Xanh lục và Xanh lam dưới dạng số hex giữa 0 và FFFF).

Bạn có thể làm tương tự cho 16 màu đầu tiên bằng xtermcontrollệnh:

$ xtermcontrol --get-color1
rgb:cdcd/0000/0000

Tuyệt vời, cảm ơn bạn rất nhiều vì sự giúp đỡ! +1
mhulse

@Gilles, bạn muốn truy vấn được gửi qua lời nhắc sau khi tiếng vang kỷ luật đầu cuối bị tắt. Xem chỉnh sửa.
Stéphane Chazelas

@ StéphaneChazelas Sử dụng một chương trình thiết bị đầu cuối (gnome-terminal) (mà là một thiết bị đầu cuối xterm) Tôi đã nhận mã của bạn để làm việc một cách chính xác (cả trong bash và zsh) Lạ lùng thay: tput colorsbáo cáo chỉ 8ngay cả khi thiết bị đầu cuối có khả năng trình bày 256 màu. Ngoài ra, màu xterm (Konsole) tput colorschỉ báo cáo 8ngay cả khi thiết bị đầu cuối đó hoàn toàn có khả năng trình bày 16 triệu màu (tất nhiên là tất cả 256 màu). Và không, không có tmux hoặc màn hình nào có thể "tô màu" :-) (thay đổi đó là) kết quả (tôi đã biết về chi tiết đó). Tóm lại: mã của bạn có thể bị lỗi trong một số thiết bị đầu cuối / bảng điều khiển.

À, tohex đã thêm vào câu trả lời của tôi, lâu hơn một chút so với những gì tôi mong đợi, nhưng 256 màu có khá nhiều điểm khó hiểu.

0

Màu ANSI trên thuật ngữ bảng điều khiển

Tùy thuộc vào giao thức hạn sử dụng giao diện điều khiển của bạn, trình tự có thể là: \e[38;5;XXXmhoặc \e[3XXXmnơi XXXtương ứng với số ansi.

Để đảm bảo bạn sử dụng đúng chuỗi ANSI, bạn phải sử dụng tput.

Liên quan đến mã thoát ANSI của Wikipedia , tôi đã viết điều này:

#!/bin/bash


for ((i=0; i<256; i++)) ;do
    echo -n '  '
    tput setab $i
    tput setaf $(( ( (i>231&&i<244 ) || ( (i<17)&& (i%8<2)) ||
        (i>16&&i<232)&& ((i-16)%6 <(i<100?3:2) ) && ((i-16)%36<15) )?7:16))
    printf " C %03d " $i
    tput op
    (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) &&
        printf "\n" ''
done

Có thể kết xuất một cái gì đó như:

nhập mô tả hình ảnh ở đây

... Sau đó, vì tôi ghét runnig hơn 200 dĩa trong một kịch bản nhỏ, tôi đã viết điều này:

#!/bin/bash

# Connector fifos directory
read TMPDIR < <(mktemp -d /dev/shm/bc_shell_XXXXXXX)

fd=3
# find next free fd
nextFd() { while [ -e /dev/fd/$fd ];do ((fd++)) ;done;printf -v $1 %d $fd;}

tputConnector() {
    mkfifo $TMPDIR/tput
    nextFd TPUTIN
    eval "exec $TPUTIN> >(LANG=C exec stdbuf -o0 tput -S - >$TMPDIR/tput 2>&1)"
    nextFd TPUTOUT
    eval "exec $TPUTOUT<$TMPDIR/tput"
}
myTput() { echo -e "$1\ncr" 1>&$TPUTIN && IFS= read -r -d $'\r' -u $TPUTOUT $2
}
tputConnector

myTput op op
myTput "setaf 7" grey
myTput "setaf 16" black
fore=("$black" "$grey")
for ((i=0; i<256; i++)) ;do
    myTput "setab $i" bgr
    printf "  %s%s  %3d  %s" "$bgr" "${fore[ i>231 && i<244||(i<17)&& (i%8<2)||
        (i>16&&i<232)&&((i-16)%6*11+(i-16)/6%6*14+(i-16)/36*10)<58
        ? 1 : 0 ]}" $i "$op"
    (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) &&
        printf "\n" ''
done

Chỉ với 1 ngã ba! Kết quả tương tự, nhưng nhanh hơn rất nhiều!

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.