Bashカラー出力が失敗する


8

セッドまたはエコーの問題ですか?私は何を間違っていますか?

$> 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が期待されたものです。

回答:


11

sed\eエスケープシーケンスとしては扱いません。GNUで、そこのsed、および他のほとんどのsedの実装\eではs、単に手段置換テキストes置換テキストで移植可能に使用できる唯一のバックスラッシュエスケープは\\、バックスラッシュ\&を意味すること、リテラルを意味すること&\/(リテラル/はデリミタ文字です)/、およびバックリファレンスのために\1スルー\9することです。GNU sedとBusyBox(たとえばOpenBSD sed以外)は\n改行を追加します。したがって、sedコマンドの出力にはリテラルが含まれeます。

bashでは、最初からリテラルエスケープ文字を変数に簡単に配置できます。構造\eによって認識されるエスケープシーケンスの1つです$'…'

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

6

echoコマンドに2つの問題があります。

簡潔にするために変数を拡張しました。

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

最初の問題:バックスラッシュは、sedマジックとシェルマジックの間のどこかで失われます。あなたはそれらを脱出する必要があります。

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

それでも動作しません。たぶんもっとエスケープ?

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

最後に、バックスラッシュが通過しています。なぜ3つのバックスラッシュが必要なのかわかりません。これは、奇妙なsedマジックです。

第二の問題:それecho -eは無意味です。-eバックスラッシュエスケープの解釈を有効にしますが、echo -e解釈されるのはすべてです"test TEST test"。バックスラッシュエスケープはsedから送られます。sedはそれらを気にせず、そのまま出力します。

あなたが欲しいのはこれです:

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

太字のTESTが出力されます。

変更された完全なスクリプトは次のとおりです。

#!/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")

ところで、echo -e "${BWhite}AAAA${ColorOff}"「\ AAAA」を表示します。regular_color_constantsとSED_color_constantsを保持する必要があるので、それは残念です。実際、私はregular_color_constantsのみを使用し、エコーとsedオプションを修正して必要なものを取得します。
ДМИТРИЙМАЛИКОВ

そのソリューションはかなり壊れやすく($stringバックスラッシュが含まれている場合はどうでしょうか)、必要以上にかなり複雑です。引用を理解するには、物事を1つずつ取り上げます。たとえば、3つのバックスラッシュはまったく魔法にかけられません。最初に二重引用符があり、これ"\\\e"は2文字の文字列\eです。その後、sed \eは「e文字どおりの文字」として理解します。
Gilles「SO-悪をやめる」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.