web-dev-qa-db-ja.com

関数内のbashプロンプトと色のエコー

私の.bashrcにこれがあります:

LIGHTGREEN="\[\033[1;32m\]"
LIGHTRED="\[\033[1;31m\]"
WHITE="\[\033[0;37m\]"
RESET="\[\033[0;00m\]"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u\$(error_test)@\w$RESET \$ "

これはシェルの出力を正確に行うようです:

username\[\]@~/

色コードの前後のエスケープ[および]がプロンプトに表示されます。色の周りからエスケープコードを削除すると機能しますが、bashの行の折り返しが大幅に失敗します。

PS1="LIGHTGREEN - whatever - $RESET"動作し、[および]はエスケープされません。しかし、私は問題のように思われる関数の中でこれを実行したいと思います。

これに関する優れたドキュメントは見つかりません。 man echoは-eオプションもリストしません。 Bashには、文書化されていないhandmedownの知識がたくさんあるようです。

46
Andy Ray

このトピックは、bash関数から\[ \]をエスケープしてbashの色を設定する方法の答えを探しているのを見つけました。

実際には解決策があります。 Bashでは、プロンプトが表示されるたびにPS1プロンプトを生成できます。

set_bash_Prompt(){
    PS1="\u@\h $(call_your_function) $>"
}

Prompt_COMMAND=set_bash_Prompt

このように、PS1はプロンプトが表示されるたびに解釈されるため、関数を呼び出し、\[ \]を含むすべてのエスケープシーケンスを適切にレンダリングします。

うまくいけば、私がこの問題を解決するために半日を費やすので、これは誰かを助けるでしょう。

49
thedk

\001の代わりに\[を使用し、\002の代わりに\]を使用します。この方法では、毎回プロンプトがリセットされるため、Prompt_COMMANDを使用した場合の結果に注意してください(これもまた、あなたが望むものにすることができます)。

関数内でカラーをエコーするbashプロンプトの解決策を説明します here

\[\]は、PS1を割り当てる場合にのみ特別です。プロンプトが表示されたときに実行される関数内でそれらを印刷すると、PS1は機能しません。この場合、バイト\001および\002を使用する必要があります

この他の答え もあり、同じ方向を指しています:

bash固有の\[および\]は実際には\001および\002に変換されます

承認されたaswerで提案されているようにPS1によって呼び出される関数内にPrompt_COMMANDを設定すると、毎回PS1がリセットされ、他のスクリプトがpromtpを簡単に変更できなくなります(例Python virtualnenv activate.sh ):

$ echo $PS1
<your PS1>
$ PS1="(TEST)$PS1"
$ echo $PS1
<(TEST) is not prepended to PS1 if you are using Prompt_COMMAND as it is reset>
26
Mauricio Robayo

\[および\]は、echoを介して出力するだけでなく、$PS*で直接使用する必要があります。

LIGHTGREEN="\033[1;32m"
LIGHTRED="\033[1;31m"
WHITE="\033[0;37m"
RESET="\033[0;00m"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u\[\$(error_test)\]@\w\[$RESET\] \$ "

my PS1コード

color_enabled() {
    local -i colors=$(tput colors 2>/dev/null)
    [[ $? -eq 0 ]] && [[ $colors -gt 2 ]]
}

BOLD_FORMAT="${BOLD_FORMAT-$(color_enabled && tput bold)}"
ERROR_FORMAT="${ERROR_FORMAT-$(color_enabled && tput setaf 1)}"
RESET_FORMAT="${RESET_FORMAT-$(color_enabled && tput sgr0)}"

# Exit code
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $BOLD_FORMAT $ERROR_FORMAT $exit_code $RESET_FORMAT " ")'

スクリーンショット(匿名化された1つのSubversionリポジトリパスを使用): Color coded output

0
l0b0

これは正常に動作します。

LIGHTGREEN="\e[32m"
LIGHTRED="\e[31m"
RESET="\e[0m"

error_test () {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}
export PS1=$(printf "$(error_test) $(whoami)@${RESET}$(pwd) ")
0
Luis Lavaire

これは古いトピックであることに気づきましたが、私はこれを関数で動作させました。トリックは、関数の印刷部分と非印刷部分を分割して、非印刷部分を[]で正しくブラケットできるようにすることです。通常、私はERROR ..行を分離するのが好きです(そして、これは問題ではありません)が、すべてが1行にある場合、これも正しく動作します。

前の$を返すことに注意してください。各サブシェルの値なので、$?次から次へと伝播します。

PS1="\n\
\[\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \$E_ERROR;
  fi
  exit \$cja_prv_retval
\`\]\
\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \"ERROR: RETURN CODE \$cja_prv_retval\";
  fi
  exit \$cja_prv_retval
\`\
\[\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \$E_RESET;
  fi
  exit \$cja_prv_retval
\`\]\
${P_RESET}${P_GRAY}\! \t ${P_RED}\u${P_GRAY}@${P_GREEN}\h ${P_YELLOW}\w ${P_CYAN}   ══>${P_RESET} "

これは私にどちらかを与えます

2021 12:28:05 cja@morpheus04 ~ ══>

エラーがない場合、または

ERROR: RETURN CODE 1 2021 12:28:16 cja@morpheus04 ~ ══>

エラーがある場合。すべてが正しく間隔が空いています(複数行の履歴編集は正しく機能します)。

0
ChrisAshton84