Что на самом деле делают `\ time`,` t \ ime` и `\ cd`? (веселье с обратными слешами в снарядах)

9

Обсуждая различия между /usr/bin/timeвстроенной оболочкой (bash и zsh) time, кто-то упомянул, что ее можно использовать \timeдля краткости /usr/bin/time.

Сначала это выглядело как хороший невинный ярлык, но затем возникли некоторые вопросы:

  • Почему тоже t\imeработает?
  • Почему \cdменяется каталог, хотя /usr/bin/cd¹ нет?

Так что, очевидно, \fooне эквивалентно $(which foo). Вопрос сейчас:

Охвачено ли наблюдаемое поведение \fooв bash и zsh каким-либо образом определением оболочки для POSIX, и если да, то почему оно ведет себя так, как оно?


Сноска 1: /usr/bin/cdв моей системе

#!/bin/sh
builtin cd "$@"
Йонас Шефер
источник
Также см. Unix.stackexchange.com/questions/12762/… Обратите внимание, что \ command - это специально задокументированная функциональность tcsh, которая говорит об игнорировании псевдонимов для команды.
simpleuser

Ответы:

14

t\imeили \cd(или "tim"eили 'cd'или ${-##*}timeили ${-+time}и любая другая комбинация цитирования и расширений, о которой вы могли бы подумать, что в конечном итоге разрешит timeили cd), такова: другой способ написать cdи time.

Тем не менее, это в конечном итоге приведет к cdили timeк более позднему времени синтаксического анализа и интерпретации оболочки. В частности, это происходит спустя долгое время после распознавания ключевых слов оболочки и замены псевдонимов .

Таким образом, в то время как оболочка ищет ключевые слова на своем языке, она не распознается ti\meкак timeключевое слово оболочки. Итак:

ti\me echo test

будет распознаваться оболочкой как простая команда, а не как timeключевое слово, за которым следует простая команда.

Затем ti\meбудет обработано цитирование (здесь обратная косая черта заключает в кавычки mсимвол, который в любом случае не нужно заключать в кавычки, символ цитирования удаляется time), и time команда будет выглядеть как любая другая команда (в списке встроенных функций). , функции и исполняемые файлы в $PATH. Скорее всего, что будет /bin/timeздесь)

Ведь в языке оболочки cdнет cdключевого слова, только cdвстроенная команда (которая имеет приоритет над вашей /usr/bin/cd). Однако, если вы определите псевдоним для cd(как alias cd=pushd), то же самое снова. Поскольку подстановка псевдонимов выполняется очень рано, перед удалением кавычек, если у вас есть псевдоним для, cdа не один для \cd(обратите внимание, что не многие оболочки допускают псевдонимы с обратными косыми чертами в них), то пишите:

\cd dir

вы убедитесь, что ваш cdпсевдоним не заменен.

Короче говоря, со ссылкой на имя команды или какую - либо его часть не мешает ему быть рассматриваются в качестве ключевого слова оболочки (ключевых слов быть вещи , как while, for, if, {... timeэто ключевое слово в некоторых только оболочках), и обходят псевдоним , вы можете иметь для него ,

Однако это не заставляет эту команду преобразовываться в исполняемый файл $PATH, команда по-прежнему ищется первой среди функций (которые вы можете обойти, выполняя command time cmd...) и встроенных функций (которые вы можете обойти, выполняя env time cmd..., хотя я не знаю, оболочка, которая имеет встроенную timeкоманду).

Обратите внимание, что цитирование может также влиять на поведение специальных встроенных элементов семейства typeset/ declare/ export/ local... в некоторых оболочках. См. Нужны ли кавычки для назначения локальной переменной? для деталей.

Стефан Шазелас
источник
Итак, разница между timeи cdчто приводит к разнице в наблюдаемом поведении в том, что timeэто ключевое слово и cdявляется встроенной командой ?
Йонас Шефер
1
@JonasWielicki, это timeключевое слово, а это cdне так. (и если бы у вас был псевдоним для cdили time, это было бы другое дело). Это cdвстроено или нет, на данный момент не имеет никакого значения (что касается влияния цитирования). Однако некоторые оболочки имеют несколько встроенных функций, которые находятся на полпути между ключевыми словами и встроенными функциями, поскольку их синтаксический анализ выполняется не так, как другие встроенные функции. Это случай export/ typeset/ declare. Я, вероятно, должен добавить примечание об этом в этом ответе.
Стефан Шазелас