Яка різниця між ехо `датою`, відлункою` `дати '' та відлунням '' дати ''?


23

Яка різниця між цими трьома командами?

echo `date`
echo "`date`"
echo '`date`'

Мене бентежить те, в чому полягають відмінності. Я думаю, що коли "навколо" це означає, що це рядок, тож ехо буквально виводить рядок dateзамість відображення дати?

Відповіді:


19

`date` просто розшириться до виводу dateкоманди. Однак він видаляє зайвий пробіл символів у місцях, де у виході є більше одного послідовного символу пробілу. (Це відбувається тому, що заміна команди підлягає розбиткові слів і тому, як echoкоманда обробляє декілька аргументів.)

У "date" " подвійні лапки - це слабкі лапки, тому вони розширять змінні (спробуйте" $ PWD ") та виконають підстановку команд. Результат розширення передається команді як єдиний аргумент echoз будь-якими послідовними пробілами: тобто розщеплення слів не виконується.

У "дати" одиничні лапки є сильнішими цитатами, тому вони не дозволять розширювати змінні чи замінювати команди всередині них.

Перейдіть за цим посиланням для отримання додаткових пояснень.

Перший пункт редагував так, як правильно вказав Майкл Суельман у коментарі нижче .


1
Як саме називається `персонаж, який оточує дату? Якщо я правильно розумію, мета символи не працюватимуть в одних цитатах?
Іван

Якщо я правильно розумію, мета символи не працюватимуть в одних цитатах?
Іван

8
За цим сценарієм `` часто називають "зворотній зв'язок" та різні документації / книги Unix. Насправді він не використовується як могильний акцент Unicode, коли він сам по собі подібний, навіть якщо це назва символу. І ви правильні, що розширення метахарактерів / виразів не відбудеться, якщо оточувати його одинарними лапками.
Джим Стюарт

Ваше перше твердження є невірним, оскільки вихід може дещо відрізнятися залежно від дати або локалі. Тільки друга команда видасть те саме, що і голою dateкомандою.
jlliagre

1
@BonsiScott Додатковий простір між "Nov" та "1" також видалено в HTML;)
Izkata

16

І те й інше

echo `date`

і

echo "`date`"

відобразиться дата. Вихід з останнього виглядає як результат із запуску dateсам по собі.

Однак є різниця: той, хто оточений "цитатами, "буде надісланий echoяк єдиний аргумент. Цитати інкапсулюють результат усієї команди як один аргумент. Оскільки echoтільки виводить свої аргументи в порядку, з пробілами між ними, вони в основному будуть виглядати однаково.

Ось приклад тонкої різниці:

echo `date`

виробляє:

Fri Nov 1 01:48:45 EST 2013

але:

echo "`date`"

виробляє:

Fri Nov  1 01:48:49 EST 2013

Зауважте, що два пробіли після Novбули зведені до одного без лапок. Це тому, що оболонка аналізує кожен розділений пробілом елемент і надсилає результат повторюватися як 6 аргументів. Коли ви цитуєте його, ехо отримує один єдиний аргумент, і лапки залишають простір.

Це стає набагато важливішим у інших командах, ніж відлуння. Наприклад, уявіть команду, fooяка бажає двох аргументів: дату та адресу електронної пошти.

Це буде працювати за таким сценарієм:

foo "`date`" joeuser@example.com

Але це заплутає сценарій, надіславши йому 7 аргументів:

foo `date` joeuser@example.com

3
Ви собі суперечать у своєму першому реченні. Перша та друга форми не завжди виводять те саме, що ви демонструєте пізніше.
jlliagre

Спасибі. Я змінив формулювання, щоб зробити це більш зрозумілим.
Джим Стюарт

3

У оболонках POSIX `date`- давня форма підстановки команд. Сучасний синтаксис є $(date).

В обох випадках вони розширюються до виводу dateз викресленими символами нового рядка (за умови, що вихід не містить символів NUL).

Однак, якщо це не в подвійних лапках і в контекстах списку (наприклад, в аргументах простих команд, як echoу вашому випадку), це розширення також підлягає:

  1. Розбиття слів : тобто "вихід dateіз позбавленими символів нового рядка" розбивається відповідно до поточного значення $IFSзмінної (за замовчуванням містить пробіл, вкладку та новий рядок (та NUL з zsh)) на кілька слів .

    Наприклад, якщо dateвиходи Fri 1 Nov 14:11:15 GMT 2013\n(як це часто буває в англійській місцевості і в материковій частині британського часового поясу), і в $IFSданий час містить :, що будуть розділити на 3 слово : Fri 1 Nov 14, 11і 15 GMT 2013.

  2. Генерація файлу (ака підстановки ) ( за виключення zsh): тобто, кожне слово в результаті розщеплення вище шукається підстановочних символи ( *, ?, [...]хоча деякі оболонки мають більш), а також розширено список імен файлів , які відповідають цим моделям. Наприклад, якщо вихід dateє ?%? 33 */*/* UVC 3432(як це часто буває в венеріанській локалей і UVC часовий пояс), і $IFSце значення за замовчуванням), то , що розширюється до всіх не прихованим 3 символів імен файлів в поточному каталозі , чий середній символ %, 33, всі не приховані файли у всіх не прихованих підкаталогах усіх не прихованих підкаталогів поточного каталогу UVCта 3432.

Ось чому:

  1. Ви завжди повинні цитувати (з подвійними лапками) підстановки команд, якщо ви не хочете, щоб розщеплення слова або генерація імені файлу виконувались після його розширення.
  2. Якщо ви хочете розділити слова , то вам слід встановити $IFSсимволи, на яких ви хочете розділити слова.
  3. Якщо ви хочете розщеплювати слова, але не створювати імена файлів , вам потрібно видати його, set +fщоб вимкнути його.

Одиночні цитати цитують все, що спричиняє сприйняття символів "backtick" буквально.

Приклад (з використанням -xполегшується зрозуміти, що відбувається):

$ 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

Якщо висновок містить символи NUL, то поведінка змінюється від оболонки до оболонки: деякі видаляють їх, деякі обрізають вихід на першому символі NUL, zshзберігають їх, але зауважте, що все одно зовнішні команди не можуть приймати аргументи, що містять NUL


Немає такого поняття, як фактична оболонка POSIX. Є оболонки, які можуть відповідати різним відповідним стандартам POSIX, використовуючи обмежений підмножина їх функціональності.
fpmurphy

0

З `date` ви отримуєте висновок дати, розділеної на кілька слів, тому що розділення слів відбувається після заміни команди.

З "date" ви отримуєте вихідну дату як одне слово / параметр, оскільки існує подмяна команд між подвійними лапками, але вихід не розбирається далі. Те саме стосується змінної розширення на зразок "$ i" у моєму прикладі нижче.

За допомогою `` date '' ви отримуєте буквальну `date ', оскільки немає заміни команд між окремими лапками.

Можливо, відмінності трьох форм будуть помітнішими таким чином:

> 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`
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.