Usar colores con printf

90

Cuando se escribe así, genera texto en azul:

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

Pero quiero tener el formato definido en printf:

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

Ahora he probado varias opciones de cómo agregar color, sin éxito:

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

Incluso intenté agregar código de atributo al formato sin éxito. Esto no funciona y no puedo encontrar un ejemplo en ninguna parte, donde se agregan colores a printf, que tiene un formato definido como en mi caso.

Jernej Jerin
fuente

Respuestas:

79

Estás mezclando las partes en lugar de separarlas limpiamente.

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

Básicamente, ponga las cosas fijas en el formato y las cosas variables en los parámetros.

geekosaurio
fuente
Gracias por tu respuesta. No lo sabía, ese formato de longitud de cadena debe colocarse entre el atributo de color.
Jernej Jerin
Esta forma de formatear (que es nueva para mí por cierto); es todo este estándar?
Chani
@Chani el printfcomando se modela después de la printf()función en lenguaje C. Allí, el primer parámetro / argumento es siempre la formatcadena que incluye todo el formato (y quizás los colores también) y el resto de los parámetros son datos. Si desea publicar texto con un estilo específico, tiene sentido colocar todos los escapes de formato y color en la cadena de formato. Tenga en cuenta que la cadena de formato se considera confiable y nunca debe contener la entrada del usuario.
Mikko Rantalainen
Algunos detalles adicionales aquí: El comando printfconsta de una cadena de formato y una lista de argumentos que se imprimen de acuerdo con el formato. Debería ver los colores como parte de la cadena de formato y, por lo tanto, deben pertenecer a la cadena de formato.
kvantour
177

En lugar de utilizar códigos terminales arcaicos, puedo sugerir la siguiente alternativa. No solo proporciona un código más legible, sino que también le permite mantener la información de color separada de los especificadores de formato tal como lo pretendía originalmente.

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

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

Vea mi respuesta AQUÍ para colores adicionales

SiegeX
fuente
1
//, Esto también hace que no tenga que documentar lo que significan los códigos. Creo que será un paso adelante para ayudar a nuestro grupo a ver los guiones como documentos.
Nathan Basanese
38

Esto funciona para mi:

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
fuente
printf "\ e [1; 34m Este es un texto azul. \ e [0m" hace exactamente lo mismo para mí.
PintoDoido
22

Este es un pequeño programa para obtener diferentes colores en la 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
fuente
9
esto es c y no bash.
Eav
14

Esta es una pequeña función que imprime texto en color usando scripts bash. Puede agregar tantos estilos como desee e incluso imprimir pestañas y nuevas líneas:

#!/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
fuente
2
¿Cuál es su política sobre la reutilización del código publicado en StackOverflow?
Daisuke Aramaki
2
@DaisukeAramaki Gracias por preguntar. Puede utilizarlo de cualquier forma y en cualquier lugar que desee. Está bajo la licencia del MIT. Si desea colaborar, no dude en enviar mejoras al Gist: gist.github.com/arianacosta/d6d1c521d231cc09ec5fe850ae2f5be1
Arian Acosta
5

Utilizo este código c para imprimir la salida de shell en color. El código se basa en esta publicación.

//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
fuente
2

man printf.1tiene una nota en la parte inferior: "... su shell puede tener su propia versión de printf...". Esta pregunta está etiquetada para bash, pero si es posible, trato de escribir scripts portátiles para cualquier shell. dashes por lo general una línea de base buena para la portabilidad mínimo - por lo que la respuesta aquí trabaja en bash, dash, y zsh. Si un script funciona en esos 3, lo más probable es que sea portátil a cualquier lugar.

La última implementación de printfen dash[1] no colorea la salida dado un %sespecificador de formato con un carácter de escape ANSI \e, pero un especificador de formato %bcombinado con octal \033(equivalente a un ASCII ESC) hará el trabajo. Por favor comente cualquier valor atípico, pero AFAIK, todos los shells se han implementado printfpara usar el subconjunto octal ASCII como mínimo.

Para el título de la pregunta "Usar colores con printf", la forma más portátil de configurar el formato es combinar el %bespecificador de formato para printf(como se menciona en una respuesta anterior de @Vlad) con un 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"

Salidas:

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

... y 'azul' es azul en la segunda línea.

El %-6sespecificador de formato del OP está en el medio de la cadena de formato entre las secuencias de caracteres de control de apertura y cierre.


[1] Ref: man dashSección "Builtins" :: "printf" :: "Formato"

AaronDanielson
fuente
-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
fuente
2
La pregunta es sobre printf en Bash, no C.
Todos los trabajadores son esenciales