PS1 = „$ (pwd)” dlaczego to działa i dlaczego różni się od PS1 = $ (pwd)

18

Dlaczego po wprowadzeniu tego polecenia wiersz zmienia się w mój katalog?

PS1='$(pwd)'

Używam pojedynczych cudzysłowów, co oznacza brak interpolacji, alias echo '$(pwd)'—— →$(pwd)

Co więcej, powiedzmy, że wyjaśniliśmy, dlaczego to działa ... dlaczego działa inaczej niż PS1=$(pwd)? (w ogóle nie ma cytatów)

Mówiąc inaczej, mam na myśli, że jeśli użyję cudzysłowów, monit będzie przechodził do mojego bieżącego katalogu podczas przeglądania terminala. Ale jeśli nie użyję cudzysłowów, to monit zawsze pozostanie katalogiem, w którym byłem, kiedy po raz pierwszy wprowadziłem poleceniePS1=$(pwd)

dlaczego?

HashWizard
źródło
2
Zapisz kilka cykli procesora i użyj równoważnego PS1 = „$ PWD”
jlliagre

Odpowiedzi:

29

Gdy po prostu przypisujesz wartość do zmiennej, $(...)wyrażenie jest oceniane, chyba że jest ujęte w pojedyncze cudzysłowy (lub znaki specjalne z odwrotnym ukośnikiem). Aby zrozumieć, spróbuj porównać te dwa:

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

Wartość parametru Anatychmiast staje się ciągiem /home/yourusernamei oczywiście nie jest pamiętane, skąd ten ciąg pochodzi, pozostaje taki sam, nawet jeśli zmienisz katalog. Wartość Bstaje się jednak dosłownym ciągiem $(pwd)bez interpretacji.

Teraz w wartości PS1czegoś wyjątkowego dzieje się: za każdym razem, gdy drukowany jest monit, interpretowane są pewne konstrukcje specjalne, np. Podstawianie poleceń $(...)jest wykonywane dokładnie tak, jak miało to miejsce powyżej przy przypisaniu do Azmiennej. Oczywiście, jeśli PS1zawiera dosłowny ciąg twojego katalogu domowego (jak wyżej z A), to nie ma możliwości, aby to zmienić. Ale jeśli zawiera ciąg $(pwd)(jak powyżej z B), to jest oceniany za każdym razem, gdy drukowany jest monit, a tym samym wyświetlany jest rzeczywisty katalog.

egmont
źródło
14

Zarówno w bash, jak i zsh, wartość PS1nie jest używana jako natychmiastowa zachęta, lecz podlega pewnym rozszerzeniom. Reguły różne dla obu powłok, ale w obydwu przypadkach jedną z etapem jest przeprowadzanie „dolara” rozszerzenia (podstawienie zmiennych, podstawień, ocena arytmetyczna) z tymi samymi składni jak w normalnym składni powłoki ( , , i , , ) .$VARIABLE${VARIABLE}$(COMMAND)`COMMAND`$((EXPRESSION))$[EXPRESSION]

  • W bash ekspansja dolara jest domyślnie włączona, ale można ją wyłączyć za pomocą shopt -u promptvars.
  • W Zsh ekspansja dolara jest domyślnie wyłączona, ale wiele osób (i większość platform konfiguracyjnych, które można znaleźć w Internecie) włącza ją setopt prompt_subst.

Przy włączonej ekspansji dolara w podpowiedzi PS1='$(pwd)'ustawiana PS1jest wartość 6-znakowa, $(pwd)co powoduje $(pwd)podstawienie, a zatem pwdpolecenie do wykonania, za każdym razem, gdy powłoka wyświetla nowy monit. Z drugiej strony, PS1=$(pwd)ustawia PS1na dowolny katalog roboczy powłoki w tym czasie. Jeśli wyłączyłeś ekspansję dolara PS1='$(pwd)', spowoduje to, że podpowiedź będzie ciągiem literalnym $(pwd).

Zauważ, że istnieją wygodniejsze sposoby uzyskania katalogu roboczego w wierszu polecenia:

  • W bashu, z odwrotnym ukośnikiem, takim jak \w, który skraca katalog domowy do ~i może zostać przycięty przez ustawienie PROMPT_DIRTRIM.
  • W zsh, z procentowym znakiem ucieczki, takim jak %/lub%~ ( %/jest taki sam jak $PWD, %~skraca katalogi domowe), który może mieć ustawienie przycinania.
  • W obu powłokach (i innych powłokach typu Bourne'a) $PWDjest to równoważne z $(pwd): nie trzeba uruchamiać podprocesu, aby uzyskać bieżący katalog roboczy.
Gilles „SO- przestań być zły”
źródło
7

Ponieważ bez cudzysłowów wartość $ (pwd) jest obliczana, gdy ustawiony jest PS1. W przypadku cudzysłowów ocena $ (pwd) jest odraczana do momentu wyświetlenia monitu.

Bez cudzysłowów PS1 jest ustawiany na bieżący katalog w momencie ustawiania PS1. W przypadku pojedynczych cudzysłowów PS1 jest ustawione na $ (pwd), co oznacza, że ​​będzie oceniać i drukować bieżący katalog za każdym razem, gdy zostanie wyświetlony monit.

farhangfarhangfar
źródło