Usando cores com printf

94

Quando escrito assim, ele produz o texto em azul:

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

Mas eu quero ter o formato definido em printf:

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

Agora tentei várias opções para adicionar cor, sem sucesso:

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

Eu até tentei adicionar código de atributo para formatar, sem sucesso. Isso não funciona e não consigo encontrar em lugar nenhum um exemplo, onde cores são adicionadas a printf, que tem formato definido como no meu caso.

Jernej Jerin
fonte

Respostas:

81

Você está misturando as partes em vez de separá-las de forma limpa.

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

Basicamente, coloque o material fixo no formato e o material variável nos parâmetros.

geekosaur
fonte
Alguns detalhes extras aqui: O comando printfconsiste em uma string de formato e uma lista de argumentos impressa de acordo com o formato. Você deve ver as cores como parte da string de formato e, portanto, elas devem pertencer à string de formato.
kvantour
ótima resposta, mudou totalmente a forma como eu estava olhando para o problema
Steven Penny
179

Em vez de usar códigos de terminal arcaicos, posso sugerir a seguinte alternativa. Ele não apenas fornece um código mais legível, mas também permite que você mantenha as informações de cores separadas dos especificadores de formato, conforme pretendido originalmente.

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

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

Veja minha resposta AQUI para cores adicionais

SiegeX
fonte
1
//, Isso também faz com que eu não precise documentar o que os códigos significam. Acho que será um passo adiante para ajudar nosso grupo a ver os scripts como documentos.
Nathan Basanese
37

Isso funciona para mim:

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

De printf(1):

%b     ARGUMENT as a string with '\' escapes interpreted, except that octal
       escapes are of the form \0 or \0NNN
Vlad
fonte
printf "\ e [1; 34mEste é um texto azul. \ e [0m" faz exatamente o mesmo para mim.
PintoDoido
20

Este é um pequeno programa para obter cores diferentes no terminal.

#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
fonte
11
este é ce não bash.
dias
14

Esta é uma pequena função que imprime texto colorido usando script bash. Você pode adicionar quantos estilos desejar e até mesmo imprimir guias e novas linhas:

#!/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
fonte
2
qual é a sua política de reutilização de código postado no StackOverflow?
Daisuke Aramaki
2
@DaisukeAramaki Obrigado por perguntar. Você pode usar de qualquer maneira e em qualquer lugar que desejar. Está sob a licença do MIT. Se você quiser colaborar, sinta-se à vontade para enviar melhorias para o Gist: gist.github.com/arianacosta/d6d1c521d231cc09ec5fe850ae2f5be1
Arian Acosta
3

Eu uso este código c para imprimir a saída do shell colorido. O código é baseado neste post.

//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
fonte
1

man printf.1tem uma nota na parte inferior: "... seu shell pode ter sua própria versão de printf...". Esta questão está marcada para bash, mas se possível, tento escrever scripts portáteis para qualquer shell. dashé geralmente uma base boa mínimo para portabilidade - então a resposta aqui trabalha em bash, dash, e zsh. Se um script funcionar nesses 3, é mais provável que seja portátil para qualquer lugar.

A implementação mais recente do printfin dash[1] não coloriza a saída dado um %sespecificador de formato com um caractere de escape ANSI \e- mas, um especificador de formato %bcombinado com octal \033(equivalente a um ASCII ESC) fará o trabalho. Por favor, comente para quaisquer outliers, mas AFAIK, todos os shells foram implementados printfpara usar o subconjunto octal ASCII no mínimo.

Para o título da pergunta "Usando cores com printf", a maneira mais portátil de definir a formatação é combinar o %bespecificador de formato para printf(como referenciado em uma resposta anterior de @Vlad) com um escape octal \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"

Saídas:

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

... e 'azul' é azul na segunda linha.

O %-6sespecificador de formato do OP está no meio da string de formato entre as sequências de caracteres de controle de abertura e fechamento.


[1] Ref: man dashSeção "Embutidos" :: "printf" :: "Formato"

AaronDanielson
fonte
-3
#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
fonte
3
A pergunta é sobre printf no Bash, não C.
All Workers Are Essential