Bash-Farbausgabe schlägt fehl

8

Ist es ein Sed- oder Echo-Problem? Was mache ich falsch?

$> cat ~/bin/color_test.sh 
#!/bin/bash

ColorOff='\e[0m'       # Text Reset
BWhite='\e[1;37m'      # Bold White

string="test TEST test"
echo -e "$string" | sed -e "s/TEST/${BWhite}TEST${ColorOff}/g"

$> ~/bin/color_test.sh 
test e[1;37mTESTe[0m test

TEST mit fetter Hervorhebung wurde erwartet.

ДМИТРИЙ МАЛИКОВ
quelle

Antworten:

11

sedwird nicht \eals Escape-Sequenz behandelt. Mit GNU sed und den meisten anderen sed-Implementierungen da draußen bedeutet \eein sErsatztext nur e. Die einzigen Backslash Fluchten Sie portably in verwenden können sErsetzungstext sind \\ein Schrägstrich bedeutet, \&wörtlich zu verstehen &, \/(wo /ist das Trennzeichen) für eine wörtliche /, und \1durch \9für Rückreferenzierungen. GNU sed und BusyBox (aber nicht zB OpenBSD sed) fügen \neine neue Zeile hinzu. Somit hat die Ausgabe Ihres sed-Befehls ein Literal e.

In Bash können Sie von Anfang an ganz einfach ein wörtliches Escape-Zeichen in Ihre Variablen einfügen. \eist eine der vom $'…'Konstrukt erkannten Escape-Sequenzen .

ColorOff=$'\e[0m'       # Text Reset
BWhite=$'\e[1;37m'      # Bold White
Gilles 'SO - hör auf böse zu sein'
quelle
6

Ihr echoBefehl enthält zwei Probleme .

Ich habe die Variablen der Kürze halber erweitert.

$ echo -e "test TEST test" | sed -e "s/TEST/\e[1;37mTEST\e[0m/g"
test e[1;37mTESTe[0m test

Erstes Problem: Die Backslashes gehen irgendwo zwischen Sed Magic und Shell Magic verloren. Du musst ihnen entkommen.

$ echo -e "test TEST test" | sed -e "s/TEST/\\e[1;37mTEST\\e[0m/g"
test e[1;37mTESTe[0m test

Funktioniert immer noch nicht. Vielleicht mehr entkommen?

$ echo -e "test TEST test" | sed -e "s/TEST/\\\e[1;37mTEST\\\e[0m/g"
test \e[1;37mTEST\e[0m test

Endlich kommen die Backslashes durch. Ich habe keine Ahnung, warum wir drei Backslashes brauchen, das ist eine seltsame Sed-Magie.

Zweites Problem: Das echo -eist sinnlos. -eermöglicht die Interpretation von Backslash-Escapezeichen, aber alles, was echo -ezu interpretieren ist, ist "test TEST test". Die Backslash-Fluchten kommen von sed, das sich nicht um sie kümmert und sie roh druckt.

Was Sie wollen, ist Folgendes:

$ echo -e $(echo "test TEST test" | sed -e "s/TEST/\\\e[1;37mTEST\\\e[0m/g")
test TEST test

mit fettem TEST in der Ausgabe.

Hier ist das vollständige Skript mit den Änderungen:

#!/bin/bash

ColorOff='\\\e[0m'       # Text Reset
BWhite='\\\e[1;37m'      # Bold White

string="test TEST test"
echo -e $(echo "$string" | sed -e "s/TEST/${BWhite}TEST${ColorOff}/g")
Lesmana
quelle
Btw, echo -e "${BWhite}AAAA${ColorOff}"zeigt `\ AAAA`. Schade, denn dann muss ich reguläre Farbkonstanten und SED-Farbkonstanten behalten. Eigentlich möchte ich nur reguläre Farbkonstanten haben und Echo- und Sed-Optionen korrigieren, um das zu bekommen, was ich will.
23 МАЛИКОВ
Diese Lösung ist ziemlich fragil (was ist, wenn sie $stringeinen Backslash enthält?) Und ist etwas komplizierter als nötig. Um das Zitieren zu verstehen, nehmen Sie die Dinge einzeln. ZB sind die drei Backslashes überhaupt keine magische Magie: Erstens gibt es doppelte Anführungszeichen und es handelt sich um eine zweistellige "\\\e"Zeichenfolge \e; dann versteht sed \eals "der Charakter ewörtlich".
Gilles 'SO - hör auf böse zu sein'