Ответ 1
Идея состоит в том, что эти три строки выполняют 3 разные вещи, если их оценивают в стандартной оболочке Bourne (sh), оболочке C (csh) или Perl. Этот хак нужен только для систем, которые не поддерживают указание имени интерпретатора, используя строку #!
в начале script. Если вы выполните Perl script, начиная с этих трех строк в качестве оболочки script, оболочка запустит интерпретатор Perl, передав ему имя файла script и аргументы командной строки.
В Perl три строки образуют один оператор, завершенный символом ;
формы
eval '...' && eval '...' & eval '...' if $running_under_some_shell;
Поскольку script только что начался, $running_under_some_shell
есть undef
, что является ложным, и оценки не выполняются. Это не-op.
Коварная часть состоит в том, что $?0
анализируется по-разному в sh против csh. В sh это означает $?
(статус выхода последней команды), за которым следует 0. Поскольку предыдущей команды нет, $?
будет 0, поэтому $?0
будет оцениваться как 00
. В csh, $?0
- специальная переменная, которая равна 1, если известно текущее имя входного файла, или 0, если это не так. Поскольку оболочка считывает эти строки из script, $?0
будет 1.
Следовательно, в sh, eval '(exit $?0)'
означает eval '(exit 00)'
, а в csh это означает eval '(exit 1)'
. Параны указывают, что команда exit должна быть оценена в подоболочке.
Как sh, так и csh понимают &&
, чтобы означать "выполнить предыдущую команду, а затем выполнить следующую команду, только если предыдущая команда вышла из 0". Таким образом, только sh будет выполнять eval 'exec perl -wS $0 ${1+"[email protected]"}'
. csh перейдет к следующей строке.
csh игнорирует "&" в начале строки. (Я точно не знаю, что это значит для csh. Его цель - сделать это одним выражением с точки зрения Perl.) Затем csh переходит к оценке eval 'exec /usr/bin/perl -wS $0 $argv:q'
.
Эти две команды очень похожи. exec perl
означает заменить текущий процесс, запустив копию perl
. -wS
означает то же, что и -w
(включить предупреждения) и -S
(найдите указанный script в $PATH
). $0
- имя файла script. Наконец, как ${1+"[email protected]"}
, так и $argv:q
создают копию текущих аргументов командной строки (соответственно в sh и csh).
Он использует ${1+"[email protected]"}
вместо более обычного "[email protected]"
для обхода ошибки в какой-то древней версии оболочки Bourne. Они означают одно и то же. Вы можете прочитать подробности в объяснение Беннета Тодда (скопировано в ответ gbacon).