
GREEN="\e[1;32m"
RED="\e[1;31m"
NONE="\e[m"
get_exit_status(){
es=$?
if [ $es -eq 0 ]
then
echo -e "${GREEN}${es}${NONE}"
else
echo -e "${RED}${es}${NONE}"
fi
}
get_path(){
#dummy function
echo "PATH"
}
PROMPT_COMMAND='exitStatus=$(get_exit_status)'
以下は正しいexitStatusを提供しますが、カラー変数は拡張されません。
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
ただし、以下は色を提供しますが、終了ステータスは更新されません。
PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
これを行う正しい方法は何ですか? ExitStatusと色の両方が機能するようにこの問題をどのように解決できますか?
答え1
Gilesはあなたの主な問題を指摘しましたが、私はこれを別の方法で説明したいと思います。
バッシュは説明した特殊プロンプトエスケープただ今後プロンプトで変数を展開します。つまり、\e
プロンプトで拡張変数を使用してから直接操作しても効果はありませんPS1
。
たとえば、期待どおりに機能し、赤いテキストが表示されます。
PS1='\e[1;31m this is in red '
しかし、そうではありません。ただ\e
プロンプトにテキストを追加するだけです。
RED='\e[1;31m'
PS1="$RED not in red "
カラーエスケープを変数に保存するには、ANSI-C引用符($'...'
)を使用して変数にリテラルエスケープ文字を配置できます。
これを行うにはGREEN
、RED
およびの定義を変更して、NONE
その値が実際のエスケープシーケンスになるようにすることができます。
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
これにより、最初の一重PS1
引用符が機能します。
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
しかし、これは2番目の問題に直面します。
実行して押し続けると、カーソルはUp Arrow行Homeの先頭に戻りません。
この問題を解決するには、カラーエスケープシーケンスをPS1
含めて\[
囲むように変更します。\]
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
get_exit_status
出力に印刷(終了コード)と印刷されていない文字(カラーコード)が含まれており、プロンプトで正しく表示できないため、ここでは正しく使用できません。配置すると、\[...\]
不完全な印刷としてマークされ、これは間違っています。正しいカラーコードを印刷してから\[...\]
プロンプトにラップするように関数を変更する必要があります。
答え2
を実行すると、PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
変数PS1
はプロンプトエスケープシーケンスであるに${RED}\h $(get_path) ${exitStatus}${NONE}
設定されます。\h
後ろにプロンプト順序が拡張(生成${RED}darkstar $(get_path) ${exitStatus}${NONE}
)され、シェルは変数拡張などの一般的な拡張を実行します。次のようなディスプレイプロンプトが表示されます\e[1;31mdarkstar PATH 0\e[m
。その過程で、\e
シーケンスを実際のエスケープ文字に拡張することはありません。
を実行すると、PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
このPS1
変数がに設定されます\e[1;31m\h PATH 0\e[m
。変数RED
、exitStatus
およびNONE
割り当て時に拡張されます。これにより、プロンプトには3つのプロンプトエスケープシーケンス(\e
、\h
および\e
再)が含まれます。この段階では、拡張可能なシェル変数はありません。
色を表示するには、実際にエスケープされた文字を含む色変数が必要です。次のことができます。
RED=$'\033[1;31m'
NONE=$'\033[m'
PS1='\[${RED}\]\h \w $?\[${NONE}\] '
$'…'
バックスラッシュ8進数シーケンスといくつかのバックスラッシュ文字シーケンスを拡張します(例\n
:)\e
。ヒントに 3 つの追加変更を適用しました。
\[…\]
色の変更コマンドなど、印刷されないシーケンスを使用します。そうしないと、bashがプロンプトの幅を計算できないため、ディスプレイが壊れます。\w
現在のディレクトリを印刷するために使用される組み込みエスケープシーケンス。- 最初から複雑な内容がない場合は、
$?
プロンプトに複雑な内容を表示する必要はありません。PROMPT_COMMAND
答え3
努力する:
PS1='`exitStatus=$?;if [ $exitStatus -eq 0 ];then echo "\['${GREEN}'\]";else echo "\['${RED}'\]";fi;echo "\h $(get_path) ${exitStatus}${NONE}"`'
答え4
ここに- これはUbuntuや他のLinux(Linuxen?)の私(TM)に適しています。
終了コード検出機能を追加する理由は、1つ$PS1
のホストが.bashrcを読み取る前に読み取り専用に設定されているためです$PROMPT_COMMAND
。