Bash:プロンプトに終了ステータスを表示する:

Bash:プロンプトに終了ステータスを表示する:
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引用符($'...')を使用して変数にリテラルエスケープ文字を配置できます。

これを行うにはGREENREDおよびの定義を変更して、NONEその値が実際のエスケープシーケンスになるようにすることができます。

GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'

これにより、最初の一重PS1引用符が機能します。

PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '

しかし、これは2番目の問題に直面します。

実行して押し続けると、カーソルはUp ArrowHomeの先頭に戻りません。

この問題を解決するには、カラーエスケープシーケンスを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。変数REDexitStatusおよび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

関連情報