Używanie kolorów z printf

90

Napisany w ten sposób wyświetla tekst na niebiesko:

printf "\e[1;34mThis is a blue text.\e[0m"

Ale chcę mieć format zdefiniowany w printf:

printf '%-6s' "This is text"

Teraz wypróbowałem kilka opcji dodawania koloru, bez powodzenia:

printf '%-6s' "\e[1;34mThis is text\e[0m"

Próbowałem nawet dodać kod atrybutu do formatu bez powodzenia. To nie działa i nie mogę nigdzie znaleźć przykładu, gdzie kolory są dodawane do printf, który ma zdefiniowany format jak w moim przypadku.

Jernej Jerin
źródło

Odpowiedzi:

79

Mieszasz części razem, zamiast czysto je rozdzielać.

printf '\e[1;34m%-6s\e[m' "This is text"

Zasadniczo umieść stałe rzeczy w formacie, a zmienne rzeczy w parametrach.

geekozaur
źródło
Dziękuję za odpowiedź. Nie wiedziałem, że format długości napisu należy umieścić między atrybutem koloru.
Jernej Jerin
Ten sposób formatowania (który przy okazji jest dla mnie nowy); czy to wszystko jest standardem?
Chani,
@Chani printfpolecenie jest wzorowane na printf()funkcji w języku C. Tam pierwszym parametrem / argumentem jest zawsze formatłańcuch, który zawiera całe formatowanie (i być może także kolory), a pozostałe parametry to dane. Jeśli chcesz wypisać jakiś tekst z określonym stylem, sensowne jest umieszczenie całego formatowania i kolorów ucieczki w ciągu formatu. Zwróć uwagę, że ciąg formatu jest uważany za zaufany i nigdy nie powinien zawierać danych wejściowych użytkownika.
Mikko Rantalainen
Oto kilka dodatkowych szczegółów: Polecenie printfskłada się z łańcucha formatu i listy argumentów, które są drukowane zgodnie z formatem. Powinieneś zobaczyć kolory jako część ciągu formatu i dlatego powinny one należeć do ciągu formatu.
kvantour
177

Zamiast używać archaicznych kodów terminali, mogę zasugerować następującą alternatywę. Nie tylko zapewnia bardziej czytelny kod, ale także pozwala zachować informacje o kolorze oddzielnie od specyfikatorów formatu, tak jak pierwotnie zamierzałeś.

blue=$(tput setaf 4)
normal=$(tput sgr0)

printf "%40s\n" "${blue}This text is blue${normal}"

Zobacz moją odpowiedź TUTAJ po dodatkowe kolory

SiegeX
źródło
1
//, To również sprawia, że ​​nie muszę dokumentować, co oznaczają kody. Myślę, że będzie to krok naprzód, aby pomóc naszej grupie zobaczyć skrypty jako dokumenty.
Nathan Basanese
38

To działa dla mnie:

printf "%b" "\e[1;34mThis is a blue text.\e[0m"

Od printf(1):

%b     ARGUMENT as a string with '\' escapes interpreted, except that octal
       escapes are of the form \0 or \0NNN
Vlad
źródło
printf "\ e [1; 34mTo jest niebieski tekst. \ e [0m" robi dokładnie to samo dla mnie.
PintoDoido
22

To jest mały program do uzyskiwania innego koloru na terminalu.

#include <stdio.h>

#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KMAG  "\x1B[35m"
#define KCYN  "\x1B[36m"
#define KWHT  "\x1B[37m"

int main()
{
    printf("%sred\n", KRED);
    printf("%sgreen\n", KGRN);
    printf("%syellow\n", KYEL);
    printf("%sblue\n", KBLU);
    printf("%smagenta\n", KMAG);
    printf("%scyan\n", KCYN);
    printf("%swhite\n", KWHT);
    printf("%snormal\n", KNRM);

    return 0;
}
Kritpal Singh
źródło
9
to jest c, a nie bash.
eav
14

Jest to mała funkcja, która drukuje kolorowy tekst za pomocą skryptów bash. Możesz dodać tyle stylów, ile chcesz, a nawet wydrukować karty i nowe linie:

#!/bin/bash

# prints colored text
print_style () {

    if [ "$2" == "info" ] ; then
        COLOR="96m";
    elif [ "$2" == "success" ] ; then
        COLOR="92m";
    elif [ "$2" == "warning" ] ; then
        COLOR="93m";
    elif [ "$2" == "danger" ] ; then
        COLOR="91m";
    else #default color
        COLOR="0m";
    fi

    STARTCOLOR="\e[$COLOR";
    ENDCOLOR="\e[0m";

    printf "$STARTCOLOR%b$ENDCOLOR" "$1";
}

print_style "This is a green text " "success";
print_style "This is a yellow text " "warning";
print_style "This is a light blue with a \t tab " "info";
print_style "This is a red text with a \n new line " "danger";
print_style "This has no color";
Arian Acosta
źródło
2
jakie są twoje zasady dotyczące ponownego wykorzystania kodu przesłanego do StackOverflow?
Daisuke Aramaki
2
@DaisukeAramaki Dzięki za pytanie. Możesz używać w dowolny sposób i gdziekolwiek chcesz. Jest na licencji MIT. Jeśli chcesz współpracować, możesz przesłać ulepszenia do Gist: gist.github.com/arianacosta/d6d1c521d231cc09ec5fe850ae2f5be1
Arian Acosta
5

Używam tego kodu c do drukowania kolorowych wyników powłoki. Kod jest oparty na tym poście.

//General Formatting
#define GEN_FORMAT_RESET                "0"
#define GEN_FORMAT_BRIGHT               "1"
#define GEN_FORMAT_DIM                  "2"
#define GEN_FORMAT_UNDERSCORE           "3"
#define GEN_FORMAT_BLINK                "4"
#define GEN_FORMAT_REVERSE              "5"
#define GEN_FORMAT_HIDDEN               "6"

//Foreground Colors
#define FOREGROUND_COL_BLACK            "30"
#define FOREGROUND_COL_RED              "31"
#define FOREGROUND_COL_GREEN            "32"
#define FOREGROUND_COL_YELLOW           "33"
#define FOREGROUND_COL_BLUE             "34"
#define FOREGROUND_COL_MAGENTA          "35"
#define FOREGROUND_COL_CYAN             "36"
#define FOREGROUND_COL_WHITE            "37"

//Background Colors
#define BACKGROUND_COL_BLACK            "40"
#define BACKGROUND_COL_RED              "41"
#define BACKGROUND_COL_GREEN            "42"
#define BACKGROUND_COL_YELLOW           "43"
#define BACKGROUND_COL_BLUE             "44"
#define BACKGROUND_COL_MAGENTA          "45"
#define BACKGROUND_COL_CYAN             "46"
#define BACKGROUND_COL_WHITE            "47"

#define SHELL_COLOR_ESCAPE_SEQ(X) "\x1b["X"m"
#define SHELL_FORMAT_RESET  ANSI_COLOR_ESCAPE_SEQ(GEN_FORMAT_RESET)

int main(int argc, char* argv[])
{
    //The long way
    fputs(SHELL_COLOR_ESCAPE_SEQ(GEN_FORMAT_DIM";"FOREGROUND_COL_YELLOW), stdout);
    fputs("Text in gold\n", stdout);
    fputs(SHELL_FORMAT_RESET, stdout);
    fputs("Text in default color\n", stdout);

    //The short way
    fputs(SHELL_COLOR_ESCAPE_SEQ(GEN_FORMAT_DIM";"FOREGROUND_COL_YELLOW)"Text in gold\n"SHELL_FORMAT_RESET"Text in default color\n", stdout);

    return 0;
}
Jonny Schubert
źródło
2

man printf.1ma na dole notatkę: „… Twoja powłoka może mieć własną wersję printf…”. To pytanie jest oznaczone jako bash, ale jeśli to możliwe, staram się pisać skrypty przenośne do dowolnej powłoki. dashjest zwykle dobrym minimalny bazowy do przenoszenia - więc odpowiedź tutaj pracuje bash, dash, i zsh. Jeśli skrypt działa w tych 3, najprawdopodobniej można go przenieść praktycznie wszędzie.

Najnowsza implementacja printfw dash[1] nie koloruje wyjścia %s, jeśli specyfikator formatu zawiera znak zmiany znaczenia ANSI \e- ale specyfikator formatu %bpołączony z ósemkowym \033(odpowiednik ASCII ESC) wykona zadanie. Proszę o komentarz dla wszelkich wartości odstających, ale AFAIK, wszystkie powłoki mają zaimplementowane, printfaby używać podzbioru ósemkowego ASCII jako minimum.

W tytule pytania „Używanie kolorów z printf” najbardziej przenośnym sposobem ustawiania formatowania jest połączenie specyfikatora %bformatu for printf(jak wspomniano we wcześniejszej odpowiedzi z @Vlad) z ósemkową ucieczką \033.


portable-color.sh

#/bin/sh
P="\033["
BLUE=34
printf "-> This is %s %-6s %s text \n" $P"1;"$BLUE"m" "blue" $P"0m"
printf "-> This is %b %-6s %b text \n" $P"1;"$BLUE"m" "blue" $P"0m"

Wyjścia:

$ ./portable-color.sh
-> This is \033[1;34m blue   \033[0m text
-> This is  blue    text

... a „niebieski” to niebieski w drugiej linii.

Specyfikator %-6sformatu z OP znajduje się w środku ciągu formatu między sekwencjami znaków sterujących otwierania i zamykania.


[1] Ref: man dashSekcja „Builtins” :: „printf” :: „Format”

AaronDanielson
źródło
-2
#include <stdio.h>

//fonts color
#define FBLACK      "\033[30;"
#define FRED        "\033[31;"
#define FGREEN      "\033[32;"
#define FYELLOW     "\033[33;"
#define FBLUE       "\033[34;"
#define FPURPLE     "\033[35;"
#define D_FGREEN    "\033[6;"
#define FWHITE      "\033[7;"
#define FCYAN       "\x1b[36m"

//background color
#define BBLACK      "40m"
#define BRED        "41m"
#define BGREEN      "42m"
#define BYELLOW     "43m"
#define BBLUE       "44m"
#define BPURPLE     "45m"
#define D_BGREEN    "46m"
#define BWHITE      "47m"

//end color
#define NONE        "\033[0m"

int main(int argc, char *argv[])
{
    printf(D_FGREEN BBLUE"Change color!\n"NONE);

    return 0;
}
Thlv
źródło
2
Pytanie dotyczy printf w Bash, a nie C.
All Workers Are Essential