Odpowiedzi:
`date` po prostu rozwinie się do wyjścia date
polecenia. Jednak usuwa dodatkowe znaki spacji w miejscach, w których na wyjściu znajduje się więcej niż jeden znak spacji. (Dzieje się tak, ponieważ podstawienie polecenia podlega podziałowi słów oraz temu, jak echo
polecenie obsługuje wiele argumentów).
W „date” podwójne cudzysłowy są słabymi cudzysłowami, więc rozwiną zmienne (spróbuj „$ PWD”) i wykonają zamianę poleceń. Wynik rozwinięcia jest przekazywany do polecenia jako pojedynczy argument echo
, z uwzględnieniem kolejnych spacji: to znaczy dzielenie słów nie jest wykonywane.
W `` date '' pojedyncze cudzysłowy są silniejszymi, więc nie pozwolą na rozszerzenie zmiennych lub podstawianie poleceń w nich.
Więcej informacji można znaleźć pod tym linkiem .
Zredagowano pierwszy punkt, jak prawidłowo wskazał Michael Suelmann w komentarzu poniżej .
date
polecenie.
Obie
echo `date`
i
echo "`date`"
wyświetli datę. Dane wyjściowe z tego ostatniego wyglądają jak dane wyjściowe z date
samego działania.
Jest jednak różnica: ten otoczony "
cytatami "
zostanie wysłany echo
jako pojedynczy argument. Cytaty zawierają wynik całej komendy jako jeden argument. Ponieważ echo
po prostu wypisuje swoje argumenty w kolejności, ze spacjami między nimi, w zasadzie będzie wyglądać tak samo.
Oto przykład subtelnej różnicy:
echo `date`
produkuje:
Fri Nov 1 01:48:45 EST 2013
ale:
echo "`date`"
produkuje:
Fri Nov 1 01:48:49 EST 2013
Zauważ, że dwa kolejne spacje Nov
zostały zredukowane do jednego bez cudzysłowów. Wynika to z tego, że powłoka analizuje każdy element oddzielony spacją i wysyła wynik do echa jako 6 argumentów. Kiedy go zacytujesz, echo otrzymuje pojedynczy argument, a cytaty zachowują spację.
Staje się to o wiele ważniejsze w poleceniach innych niż echo. Na przykład wyobraź sobie polecenie, foo
które chce dwóch argumentów: daty i adresu e-mail.
Będzie to działać w tym scenariuszu:
foo "`date`" joeuser@example.com
Spowoduje to jednak pomieszanie skryptu poprzez wysłanie 7 argumentów:
foo `date` joeuser@example.com
W powłokach POSIX `date`
jest starożytną formą zastępowania poleceń. Współczesna składnia to $(date)
.
W obu przypadkach są one rozszerzane do wyniku date
z usuniętymi końcowymi znakami nowego wiersza (pod warunkiem, że wynik nie zawiera znaków NUL).
Jednakże, gdy nie znajduje się w podwójnym cudzysłowie i w kontekstach listy (na przykład w argumentach prostych poleceń, jak echo
w twoim przypadku), to rozwinięcie podlega ponadto:
Dzielenie wyrazów : to znaczy „wynik date
z usuniętymi końcowymi znakami nowej linii” jest dzielony zgodnie z bieżącą wartością $IFS
zmiennej (domyślnie zawierającej spację, tabulator i znak nowej linii (i NUL z zsh
)) na kilka słów .
Na przykład, jeśli date
wyjścia Fri 1 Nov 14:11:15 GMT 2013\n
(jak to często robi w lokalizacji angielskiej i kontynentalnej w brytyjskiej strefie czasowej) i $IFS
obecnie zawiera :
, które zostaną podzielone na 3 słowach : Fri 1 Nov 14
, 11
i 15 GMT 2013
.
zsh
), to znaczy każde słowo wynikające z podziału powyżej jest szukali znaków wieloznacznych ( *
, ?
, [...]
choć niektóre muszle mają więcej), a rozszerzony do listy nazw plików pasujących do tych wzorców. Na przykład, jeśli wyjście date
jest ?%? 33 */*/* UVC 3432
(jak to często jest w Wenus lokalizacjach i UVC strefy czasowej), i $IFS
jest to wartość domyślna), to rozwija się do wszystkich nie-ukryty 3 nazwami znaków w bieżącym katalogu, którego środkowa postać jest %
, 33
, wszystkie nie ukryte pliki we wszystkich nie ukrytych podkatalogach wszystkich nie ukrytych podkatalogów bieżącego katalogu, UVC
oraz 3432
.Dlatego:
$IFS
znaki, na które chcesz dzielić.set +f
aby je wyłączyć.Pojedyncze cytaty cytują wszystko, więc dosłownie należy traktować znaki z tyłu.
Przykład (użycie -x
ułatwia sprawdzenie, co się dzieje):
$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri 1 Nov 14' 42 '33 GMT 2013'
Fri 1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri 1 Nov 14:42:41 GMT 2013'
Fri 1 Nov 14:42:41 GMT 2013
bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432
Jeśli dane wyjściowe zawierają znaki NUL, zachowanie różni się w zależności od powłoki: niektóre usuwają je, niektóre obcinają dane wyjściowe przy pierwszym znaku NUL, zsh
zachowują je, ale należy pamiętać, że w każdym razie polecenia zewnętrzne nie mogą przyjmować argumentów zawierających wartości NUL
Za pomocą `date` otrzymujesz wynik daty podzielony na wiele słów, ponieważ dzielenie słów odbywa się po zastąpieniu polecenia.
Za pomocą „data” otrzymujesz wynik daty jako jedno słowo / parametr, ponieważ pomiędzy podwójnymi cudzysłowami występuje polecenie, ale wynik nie jest dalej analizowany. To samo dotyczy rozszerzenia zmiennej, takiego jak „$ i” w moim przykładzie poniżej.
Z „data” dostajesz dosłowną „datę”, ponieważ nie ma podstawienia poleceń między pojedynczymi cudzysłowami.
Być może różnice między 3 postaciami będą bardziej widoczne w ten sposób:
> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013
> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013
> for i in '`date`'; do echo "$i"; done
`date`