Ist es möglich, die Schriftfarben im Terminal zu ändern, ohne das Auffüllformat „% * s“ von printf zu beeinflussen?

7

Ich habe eine Funktion in einem Bash-Skript message_offset, mit der der Status eines Bash-Skripts gedruckt wird.
Das heißt, Sie würden es als Übergabe einer Nachricht und eines Status wie diesen bezeichnen

message_offset "install font library" "[   OK   ]" 

und es würde in das Terminal gedruckt, wo printfdas %*sFormat verwendet wird, um immer das Zeichen ganz rechts mit einer [ OK ]Breite von 80 Spalten festzulegen, z. B. wäre die Ausgabe

install font library                              [   OK   ]
update configuration file on server               [   ERR  ]
                                                           ^
                                                           |
                                                      always
                                                        at 80

Wenn echoverwendet, würde die Ausgabe so aussehen

install font library                 [   OK   ]
update configuration file on server               [   ERR  ]

Code:

#!/usr/bin/env bash

function message_offset() {

    local message="$1"
    local status="$2"

    # compensate for the message length by reducing the offset 
    # by the length of the message, 
    (( offset = 80 - ${#message} ))

    # add a $(tput sgr0) to the end to "exit attributes" whether a color was
    # set or not
    printf "%s%*s%s" "${message}" 80 "$status" "$(tput sgr0)"

}

Dies alles funktioniert in Ordnung, bis ich versuche, tputeinige Farbsequenzen in die Zeichenfolge einzufügen, dh "[ERR]" rot zu machen.
Es scheint, dass die printf "%*s"Formatierung die tput-Zeichenfolgen zählt, wenn der Offset eingestellt wird. Wenn ich also die Funktion so aufrufe

message_offset "update configuration file on server"  "$(tput setaf 1)[   ERR  ]"

Die Ausgabe sieht ungefähr so ​​aus:

install font library                              [   OK   ]
update configuration file on server          [   ERR  ]

weil printf "%*s"gesagt wird, hey, diese Zeichenfolge hat alle "[ ERR ]"Zeichen plus die "$(tput setaf 1)Zeichen, aber offensichtlich werden die "$(tput setaf 1)Zeichen nicht gedruckt, also beeinflussen Sie die Auffüllung nicht wirklich.
Gibt es eine Möglichkeit, die "Status" -Nachrichten tputfarbig zu gestalten und auch die Stilfarbsequenzen zu verwenden?

the_velour_fog
quelle

Antworten:

8

Du machst das viel komplizierter als es sein sollte. Sie können die Ausrichtung mit $messageder Breite von ANSI-Sequenzen handhaben und sich nicht darum kümmern:

#! /usr/bin/env bash

message() {
    [ x"$2" = xOK ] && color=2 || color=1
    let offset=$(tput cols)-4-${#2}
    printf "%-*s[ %s%s%s ]\n" $offset "$1" "$(tput setaf "$color")"  "$2" "$(tput sgr0)"
}  

message "install font library" "OK"
message "update configuration file on server" "ERR"

Bearbeiten: Bitte beachten Sie, dass die meisten printf(1)Implementierungen Längenberechnungen für Multibyte-Zeichensätze nicht gut verarbeiten. Wenn Sie also Nachrichten mit Akzentzeichen in UTF-8 drucken möchten, benötigen Sie möglicherweise einen anderen Ansatz. zucken

Satō Katsura
quelle
Danke, das funktioniert und ist definitiv sauberer. Jetzt versuche ich zu verstehen, wie Ihr Code funktioniert. Können Sie mir zum Beispiel sagen, was der Unterschied zwischen den Formaten printf %*sund printf %-*sist?
the_velour_fog
@the_velour_fog $(tput cols)= Terminalbreite, printf '%-*s' $offset "$1"druckt die Nachricht linksbündig und füllt sie mit Leerzeichen bis zur Breite nach rechts $offset. Das ist im Wesentlichen alles, was dazu gehört.
Satō Katsura
hmm, ich verstehe es immer noch nicht, aber es scheint, printf '%-*s'ist der Schlüssel hier?
the_velour_fog
Versuchen Sie dies: printf '%10s|\n' aaadann printf '%-10s|\n' aaa, dannprintf '%-*s|\n' 10 aaa
Satō Katsura
Ah, danke, verstanden. Ja %-*sist im Wesentlichen "absolute" Polsterung, unabhängig davon, wie lang sie %sist, während sie %*s"relativ zum rechten Rand des vorherigen Wortes" ist. Danke Sato :)
the_velour_fog
1

ein einfacher Ansatz ist , alles kolorieren nach ihm ausgerichtet wurde

Kurz gesagt, Sie brauchen

  • Eine Funktion (oder besser ein externes Skript) zum Färben von Zeichenfolgen mit Farben (z. B. mithilfe von Perls s,$regex,$color$&$resetcolor,gi

  • und Sie rufen es auf, nachdem Sie den Druck ausgeführt haben. Farb-Escape-Codes ändern die Ausrichtung auf diese Weise nicht.

Beispiel: Nehmen wir an, Sie haben ein Skript mit dem Namen "colorize" erstellt, das Farbargumente verwendet, gefolgt von regulären Ausdrücken, die mit dieser Farbe eingefärbt werden sollen. Beispiel: colorize -blue 'regex1' -green 'regex2' Sie nennen es bei Bedarf:

 { code
   that
  formats and display things
 } | colorize -red 'ERR' -green 'OK'

Wenn Sie das als Skript für sich haben, können Sie es überall verwenden, zum Beispiel:

 df -h | colorize -red '[890].%'
Olivier Dulac
quelle