PS1とPROMPT_COMMANDの違いは何ですか


108

見ながら、この素晴らしいスレッドを私はいくつかの例を使用していることに気づきました

PS1="Blah Blah Blah"

そしていくつかの使用

PROMPT_COMMAND="Blah Blah Blah"

(および両方を使用する場合もあります)bashシェルでプロンプトを設定する場合。2つの違いは何ですか?SO検索と少し広いgoogle検索でさえ結果が得られないので、答えを探すための適切な場所へのリンクでさえいただければ幸いです。

回答:



67

PROMPT_COMMANDには通常のbashステートメントを含めることができますが、PS1変数には、変数にホスト名の「\ h」などの特殊文字を含めることもできます。

たとえば、PROMPT_COMMANDとPS1の両方を使用する私のbashプロンプトは次のとおりです。PROMPT_COMMANDのbashコードは、現在のgitブランチを特定し、最後の実行プロセスの終了ステータス、pwdのホスト名とベース名とともにプロンプ​​トに表示します。変数RETは、最後に実行されたプログラムの戻り値を格納します。これは、エラーが発生したかどうか、およびターミナルで最後に実行したプログラムのエラーコードを確認するのに便利です。PROMPT_COMMAND式全体を囲む '外側に注意してください。これにはPS1が含まれているため、PROMPT_COMMAND変数が評価されるたびにこの変数が再評価されます。

PROMPT_COMMAND='RET=$?;\
  BRANCH="";\
  ERRMSG="";\
  if [[ $RET != 0 ]]; then\
    ERRMSG=" $RET";\
  fi;\
  if git branch &>/dev/null; then\
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2);\
  fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'

出力例は、非gitディレクトリでは次のようになります。

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $ 

gitディレクトリにブランチ名が表示されます。

sashan@dhcp-au-122 rework mybranch $ 

更新

コメントとボブの答えを読んだ後、彼が説明するようにそれを書く方が良いと思います。PS1変数がPROMPT_COMMAND内に設定されている上記で最初に書いたものよりも保守しやすいです。PROMPT_COMMAND自体は、実行時にbashによって評価される非常に複雑な文字列です。機能しますが、必要以上に複雑です。公平を期すために、私は約10年前に自分でPROMPT_COMMANDを書いたが、それは機能し、あまり考えていなかった。

私が自分の状況をどのように修正したかについて知りたい人のために、基本的にはPROMPT_COMMANDのコードを(Bobが説明したように)別のファイルに入れてから、PS1にするつもりの文字列をエコーし​​ます。

GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
    ERRMSG=" $RET"
fi
if which git &>/dev/null; then
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2)
else
    BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"

そして私の.bashrc

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

1
行の1つを短くすることができます:if git branch &>/dev/null ; then\ 。stdoutとstderrの両方を/ dev / nullにリダイレクトします。tldp.org/LDP/abs/html/io-redirection.html

3
エクスポート する必要はありませんPROMPT_COMMAND
ドルメン2016

2
私はのcevingコメントがあまりにもこの答えのための本当の大変だと思う:Don't set PS1 in PROMPT_COMMAND! Set variables in PROMPT_COMMAND and use them in PS1
phil294

2
理由はわかりません。なぜPS1オンラインでの変更PROMPT_COMMANDは不利なのでしょうか。それは完全に便利なコードです。ボブの答えが下であるのとは対照的に、PS1変数は正しく構築されました。これにより、実際の状況に応じて、より高度なbashプロンプトを使用できます。
クリスチャンウルフ

2
PS1内部の@ChristianWolf構造は意味を持ちPROMPT_COMMANDません。それはそれをしない方法の例です。PS1一度構築すると.bash_profile、二重引用符の代わりに一重引用符を使用するだけで、各プロンプトで変数の置換が評価されます。
友人、

46

違いは、PS1が実際に使用されるプロンプト文字列であり、PROMPT_COMMANDがプロンプトの直前に実行されるコマンドであることです。プロンプトを作成する最も簡単で柔軟な方法が必要な場合は、次のことを試してください。

これを.bashrcに入れてください:

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

次に、スクリプト(bash、perl、ruby:選択)を記述し、それを〜/ bin / bash_promptに配置します。

スクリプトは、プロンプトを作成するために好きな情報を使用できます。PS1変数用に開発されたいくぶんバロック的な置換言語を学ぶ必要がないため、これはIMOをはるかに単純化します。

PROMPT_COMMANDを〜/ bin / bash_promptに直接設定し、PS1を空の文字列に設定するだけで同じことができると思うかもしれません。これは最初は機能しているように見えますが、すぐに、readlineコードがPS1が実際のプロンプトに設定されることを期待していることを発見し、履歴のバックワードをスクロールすると、結果が混乱します。この回避策により、PS1は常に最新のプロンプトを反映します(関数はシェルの呼び出しインスタンスによって使用される実際のPS1を設定するため)。これにより、readlineとコマンド履歴が正常に機能します。


17
設定しないでくださいPS1PROMPT_COMMAND!で変数を設定しPROMPT_COMMAND、で使用しますPS1。そうしないと、またはのPS1ようなエスケープシーケンスを使用できなくなります。でそれらを再発明する必要があります。それは可能かもしれないが、それはの失う回避することはできませんし、これ以外の印刷可能文字の始まりと終わりをマーク。これは、プロンプトの長さについて端末を混乱させずに色を使用できないことを意味します。そして、これは2行を生成するコマンドを編集するときに混乱します。最後に、画面上に大きな混乱があります。\u\hPROMPT_COMMAND\[\]readline
2015年

1
@ceving True that!PROMPT_COMMANDを使用してPS1 のフォーマットを変更し、両方の世界のベストを手に入れることができます
2grit

3
PROMPT_COMMAND印刷前に実行されますPS1。終了後にシェルが印刷されるのでPS1、内部からの設定に問題はありません。変更されたシェル(この場合は内部)が表示されますか?PROMPT_COMMANDPROMPT_COMMANDPS1PROMPT_COMMANDprompt_command
フェリペアルバレス

3
警告:通常、PROMPT_COMMANDを使用して文字をプロンプトに直接出力することはできません。PS1の外で印刷された文字はBashによってカウントされないため、カーソルが正しく配置されず、文字がクリアされます。PROMPT_COMMANDを使用してPS1を設定するか、埋め込みコマンドを確認してください。(Arch Wikiソース
meffect

3
誰もがだけではなく、PS1でコマンド置換を使用してのPROMPT_COMMAND中でいくつかのトリックを行うにしようと、なぜ私はそれを得ることはありませんexport PS1='$(~/bin/bash_prompt)'同じことのバグは正気に見えない
PAL

10

からman bash

PROMPT_COMMAND

設定されている場合、値は各プライマリプロンプトを発行する前にコマンドとして実行されます。

PS1

このパラメーターの値は展開され(下記のプロンプトを参照)、プライマリプロンプト文字列として使用されます。デフォルト値は '' \ s- \ v \ $ ''です。

プロンプト文字列を設定するだけの場合PS1は、単独で使用するだけで十分です。

PS1='user \u on host \h$ '

プロンプトを出力する直前に他のことをしたい場合は、を使用してくださいPROMPT_COMMAND。たとえば、キャッシュされた書き込みをディスクに同期する場合は、次のように記述できます。

PROMPT_COMMAND='sync'

1
また、端末からのタイトルを設定することができPS1なくてもPROMPT_COMMANDタイトルを設定するシーケンスが中に含ませることができるよう、PS1でラップ\[\]
ドルメン

1
@dolmen大丈夫。次に、環境変数を動的に設定するなど、他のことをしましょう。
Cyker 2016

@CykerではPS1、環境変数を動的に設定できます。それはサブシェルで設定されるだけなので、その値を取得することはできません。しかし、あなたの例は取るに足らないものですPS1='$(sync)user \u on host \h$ '
パル

1

違いは

  • から不完全な行を出力PROMPT_COMMANDすると、bashプロンプトが台無しになります
  • PS1代理人\Hと友達
  • PROMPT_COMMANDその内容を実行し、PS1その内容をプロンプトとして使用します。

PS1各プロンプトで変数展開とコマンド置換を行います。PROMPT_COMMAND値を割り当てPS1たり、任意のコードを実行したりする必要はありません。あなたは簡単にexport PS1='$(uuidgen) $RANDOM'一度で行うことができ.bash_profile、単一引用符を使用するだけです


0

うん、それで本当にこれを釘付けにしようとするために:

  • PROMPT_COMMAND便利なbashの便利な変数/関数ですが、厳密に言えば、PS1単独で使用することもできないことはありますか?

つまり、プロンプトの外側にスコープを持つ別の変数を設定し たい場合:シェルによっては、その変数をおそらく最初に外部で宣言する必要があるか、または(最悪の場合)先にFIFOで待機する何かを凝らさなければならない場合があります呼び出す(そしての終わりに再び武装する); これは、特にいくつかの派手な正規表現を使用している場合に、問題を引き起こす可能性があります。しかし、それ以外の場合:コマンド置換を使用して(そして、場合によっては、明示的なサブシェルを使用して)、何でも実行できますか?$PS1$PS1$PS1\u \hPROMPT_COMMAND$PS1

正しい?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.