Кажется, есть некоторая несогласованность, которую я не могу понять в отношении оболочки bash.
Если я выполню:
ls;date;time
результаты трех запросов будут показаны последовательно.
Однако, при смене даты и времени, появляется сообщение об ошибке.
Поэтому, если я выполню:
ls;time;date
сообщение об ошибке гласит: bash: syntax error near unexpected token 'date'
.
Может кто-нибудь объяснить это?
Bash рассматривает встроенное time
как особый случай, при парсинге командных строк.
Как может быть считан в странице справочника удара, строка, как введено сначала разделяется на список:
pipeline ; pipeline
где конвейер:
[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]
или в нашем случае, просто:
time command
т.е. если время присутствует, то управляйте, должен также присутствовать.
[Существует особый случай, который позволяет time
чтобы сопровождаться новой строкой, но это не применяется здесь]
Так, в нашем случае мы имеем:
time;date
быть разделенным на два конвейера:
1. time
2. date
и конвейер 1 не хорошо формируется, так как мы имеем time
без команды. Следовательно ошибка.
Обратите внимание что командная строка time
не работает здесь также:
$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
колотите анализирует это как ожидалось, в 2 конвейера:
1. /usr/bin/time
2. date
и /usr/bin/time
затем отказывается работать без аргумента. Обратите внимание, что это - ошибка от /usr/bin/time
не ошибка от удара.
Причина, что обратная галочка работает, состоит в том, что обратная галочка останавливается time
будучи интерпретируемым как специальный элемент в конвейере.
т.е. с обратной галочкой:
`time`;date
это анализируется как два конвейера:
1. `time`
2. date
Помните, что конвейер, в нашем случае:
[time] command
и проблема первоначально состояла в том, что мы имели time
без команды, которая не позволяется. Но теперь у нас просто есть команда:
`time`
без предыдущего time
, так как обратные галочки означают это time
интерпретируется как команда, не как предыдущее слово.
Таким образом, удар затем выполняет свое встроенное time
без args, который принят. Это не производит вывода, и мы не видим ошибки.
Обратите внимание что:
`time`
на самом деле выполняет результат time
встроенный, т.е. это работает что time
встроенные продукты на stdout. Но с тех пор time
самостоятельно ничего не пишет в stdout, это, кажется, работает.
Наконец, было отмечено, что это работает:
time ; ; date
который я не могу объяснить, печально :)
Команда time
в вашем конвейере является не двоичным /usr/bin/time
, а встроенным в bash time
. Сравните man time
с help time
. Ошибка, которую вы видите, заключается в том, что bash не удалось разобрать аргумент time
. Это должно присутствовать или быть новой строкой. Это символ новой строки в вашем первом примере, но отсутствует во втором.
С другой стороны, если вы запустили
ls;date;'time'
или
ls;'time';date
, где кавычки вокруг 'time'
отменяют его статус как зарезервированное слово, тогда bash имеет нет проблем с разбором строки. Теперь он анализирует три команды в списке, которые он будет выполнять последовательно, и /usr/bin/time
сообщит об ошибке использования в любом случае.
Приложение
Было замечено, что хотя time ; date
приводит к ошибке, time ; ; date
нет. Вероятное объяснение состоит в том, что time ;
интерпретируется bash как эквивалентное time <newline>
. Выражение time ; ; date
затем анализируется как список time ;
и date
.
Это согласуется с наблюдением, что time ;
и time ; ;
также являются законными, второй анализируется как одноэлементный список, содержащий time ;
, за которым следует необязательная точка с запятой, разрешенная после списков.
Итак, еще один способ объяснить, почему time ; date
приводит к ошибке bash: syntax error near unexpected token 'date'
, состоит в том, что time
использует точку с запятой, отделяющую ее от date
. Это может быть сделано только потому, что time
является зарезервированным словом bash.