web-dev-qa-db-ja.com

PS1 = '$(pwd)'なぜこれが機能し、なぜこれがPS1 = $(pwd)と異なるのか

このコマンドを入力すると、プロンプトがディレクトリに変わるのはなぜですか?

_PS1='$(pwd)'
_

私は一重引用符を使用しています。これは補間がないことを意味します。別名echo '$(pwd)'-→$(pwd)

さらに、これが機能する理由を明らかにしたとしましょう...なぜPS1=$(pwd)とは異なる機能をするのですか? (まったく引用なし)

別の言い方をすると、引用符を使用すると、ターミナルをナビゲートするときにプロンプ​​トが現在のディレクトリに変わり続けます。ただし、引用符を使用しない場合、最初にコマンドを入力したときのプロンプトは常にPS1=$(pwd)のままになります。

どうして?

18
HashWizard

変数に値を割り当てるだけの場合、$(...)式は、単一引用符で囲まれていない(またはバックスラッシュでエスケープされている)場合を除き、評価されます。理解するには、次の2つを比較してみてください。

_A=$(pwd)
echo "$A"
B='$(pwd)'
echo "$B"
_

Aの値はすぐに文字列_/home/yourusername_になり、明らかにこの文字列がどこから来たかは記憶されておらず、ディレクトリを変更しても同じままです。ただし、Bの値は、解釈されずにリテラル文字列$(pwd)になります。

ここで、_PS1_の値で何か特別なことが起こります。プロンプトが出力されるたびに、特定の特別な構成が解釈されます。コマンド置換$(...)は、上記のA変数への割り当てで発生したとおりに実行されます。もちろん、_PS1_にホームディレクトリのリテラル文字列が含まれている場合(上記のAの場合と同様)、変更する方法はありません。ただし、文字列$(pwd)が含まれている場合(上記のBの場合と同様)、プロンプトが出力されるたびに評価され、実際のディレクトリが表示されます。

29
egmont

Bashとzshの両方で、_PS1_の値はそのままプロンプトとして使用されず、いくつかの拡張が行われます。ルールは2つのシェルで異なりますが、どちらの場合も、ステップの1つは、通常のシェル構文(_$VARIABLE_、と同じ構文で「ドル」展開(変数置換、コマンド置換、算術評価)を実行することです。 _${VARIABLE}_、$(COMMAND)または_`COMMAND`_、$((EXPRESSION))、_$[EXPRESSION]_)。

  • Bashでは、ドルの拡張はデフォルトでオンになっていますが、 _shopt -u promptvars_ でオフにできます。
  • Zshでは、ドル拡張はデフォルトでオフになっていますが、多くの人(およびWebで見つけるほとんどの構成フレームワーク)は _setopt Prompt_subst_ でオンにします。

プロンプトでドル拡張をオンにすると、PS1='$(pwd)'は_PS1_を6文字の値$(pwd)に設定し、$(pwd)を置換します。したがって、シェルが新しいプロンプトを表示するたびにpwdコマンドが実行されます。一方、PS1=$(pwd)は_PS1_を、その時点でシェルの現在の作業ディレクトリに設定します。ドル展開をオフにした場合、PS1='$(pwd)'を指定すると、プロンプトがリテラル文字列$(pwd)になります。

プロンプトで作業ディレクトリを取得するより便利な方法があることに注意してください。

  • Bashでは、_\w_などの バックスラッシュエスケープ を使用して、ホームディレクトリを_~_に短縮し、_Prompt_DIRTRIM_を設定することでトリミングできます。
  • Zshでは、 _%/_または_%~_ (_%/_は_$PWD_と同じです)などの パーセントエスケープ _%~_はホームディレクトリを省略します)。トリミング設定を行うことができます。
  • いずれかのシェル(およびその他のBourneスタイルのシェル)では、_$PWD_は$(pwd)と同等です。現在の作業ディレクトリを取得するためにサブプロセスを実行する必要はありません。

引用符がないため、PS1が設定されているときに$(pwd)が評価されます。引用符を使用すると、$(pwd)の評価はプロンプトが表示されるまで延期されます。

引用符がない場合、PS1は、PS1の設定時に現在のディレクトリに設定されます。一重引用符を使用すると、PS1は$(pwd)に設定されます。つまり、プロンプトが表示されるたびに現在のディレクトリが評価されて印刷されます。

7