Utilisation des couleurs avec printf

90

Lorsqu'il est écrit comme ceci, il affiche le texte en bleu:

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

Mais je veux que le format soit défini dans printf:

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

Maintenant, j'ai essayé plusieurs options pour ajouter de la couleur, sans succès:

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

J'ai même essayé d'ajouter un code d'attribut au format sans succès. Cela ne fonctionne pas et je ne trouve nulle part un exemple, où les couleurs sont ajoutées à printf, qui a défini le format comme dans mon cas.

Jernej Jerin
la source

Réponses:

79

Vous mélangez les pièces ensemble au lieu de les séparer proprement.

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

Fondamentalement, mettez les éléments fixes dans le format et les éléments variables dans les paramètres.

geekosaure
la source
Merci pour vos vêtements. Je ne savais pas, ce format de longueur de chaîne doit être placé entre l'attribut de couleur.
Jernej Jerin
Cette façon de mettre en forme (qui est nouvelle pour moi d'ailleurs); est tout ce standard?
Chani
@Chani la printfcommande est modélisée d'après la printf()fonction en langage C. Là, le premier paramètre / argument est toujours la formatchaîne qui inclut tout le formatage (et peut-être aussi les couleurs) et le reste des paramètres sont des données. Si vous souhaitez mettre du texte avec un style spécifique, il est logique de mettre toutes les mises en forme et les échappements de couleur dans la chaîne de format. Notez que la chaîne de format est considérée comme approuvée et ne doit jamais contenir d'entrée utilisateur.
Mikko Rantalainen
Quelques détails supplémentaires ici: La commande se printfcompose d'une chaîne de format et d'une liste d'arguments qui s'impriment selon le format. Vous devriez voir les couleurs comme faisant partie de la chaîne de format et par conséquent, elles devraient appartenir à la chaîne de format.
kvantour
177

Plutôt que d'utiliser des codes terminaux archaïques, puis-je suggérer l'alternative suivante. Non seulement il fournit un code plus lisible, mais il vous permet également de séparer les informations de couleur des spécificateurs de format comme vous l'aviez initialement prévu.

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

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

Voir ma réponse ICI pour des couleurs supplémentaires

SiegeX
la source
1
//, Cela fait aussi que je n'ai pas à documenter ce que signifient les codes. Je pense que ce sera un pas en avant pour aider notre groupe à voir les scripts comme des documents.
Nathan Basanese
38

Cela fonctionne pour moi:

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
la source
printf "\ e [1; 34mCeci est un texte bleu. \ e [0m" fait exactement la même chose pour moi.
PintoDoido
22

Ceci est un petit programme pour obtenir une couleur différente sur le 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
la source
9
c'est c et pas bash.
eav
14

Il s'agit d'une petite fonction qui imprime du texte en couleur à l'aide de scripts bash. Vous pouvez ajouter autant de styles que vous le souhaitez, et même imprimer des onglets et de nouvelles lignes:

#!/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
la source
2
Quelle est votre politique de réutilisation du code publié sur StackOverflow?
Daisuke Aramaki
2
@DaisukeAramaki Merci d'avoir demandé. Vous pouvez l'utiliser de n'importe quelle manière et n'importe où. C'est sous la licence MIT. Si vous souhaitez collaborer, n'hésitez pas à soumettre des améliorations au Gist: gist.github.com/arianacosta/d6d1c521d231cc09ec5fe850ae2f5be1
Arian Acosta
5

J'utilise ce code c pour imprimer la sortie de la coque colorée. Le code est basé sur ce 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
la source
2

man printf.1a une note en bas: "... votre shell peut avoir sa propre version de printf...". Cette question est balisée bash, mais si c'est possible, j'essaye d'écrire des scripts portables sur n'importe quel shell. dashest généralement une bonne base minimum pour la portabilité - donc la réponse fonctionne ici bash, dash, &zsh . Si un script fonctionne dans ces 3, il est très probable qu'il soit portable à peu près n'importe où.

La dernière implémentation de printfin dash[1] ne colorise pas la sortie étant donné un %sspécificateur de format avec un caractère d'échappement ANSI \e- mais, un spécificateur de format %bcombiné avec octal \033(équivalent à un ASCII ESC) fera le travail. Veuillez commenter les valeurs aberrantes, mais AFAIK, tous les shells ont été implémentés printfpour utiliser le sous-ensemble octal ASCII au strict minimum.

Au titre de la question "Utiliser les couleurs avec printf", le plus portable de définir le formatage est de combiner le %bspécificateur de format pour printf(comme indiqué dans une réponse précédente de @Vlad) avec un échappement 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"

Les sorties:

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

... et «bleu» est bleu sur la deuxième ligne.

Le %-6sspécificateur de format de l'OP se trouve au milieu de la chaîne de format entre les séquences de caractères de contrôle d'ouverture et de fermeture.


[1] Réf: man dashSection "Builtins" :: "printf" :: "Format"

AaronDanielson
la source
-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
la source
2
La question concerne printf dans Bash, pas C.
Tous les travailleurs sont essentiels