В документации по Perl perlrun (1) предлагает запустить сценарии Perl с использованием двуязычного заголовка оболочки / Perl:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
Что ${1+"$@"}
значит? Я попытался использовать "$@"
вместо этого (используя Bash как / bin / sh), и это, кажется, работает так же хорошо.
редактировать
Два ответа ниже говорят, что это должно быть ${1:+"$@"}
. Мне известен ${parameter:+word}
синтаксис («Использовать альтернативное значение»), описанный в bash (1). Тем не менее, я не уверен, потому что
Оба
${1+"$@"}
и"$@"
работают просто отлично, даже когда нет параметров. Если я создаю simple.sh как#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
и вопрос.ш как
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Я могу заставить оба работать одинаково:
$ ./question.sh $VAR1 = []; $ ./question.sh a $VAR1 = [ 'a' ]; $ ./question.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./question.sh "" $VAR1 = [ '' ]; $ ./simple.sh $VAR1 = []; $ ./simple.sh a $VAR1 = [ 'a' ]; $ ./simple.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./simple.sh "" $VAR1 = [ '' ];
Другие источники в Интернете также используют
${1+"$@"}
, в том числе один хакер, который, кажется, знает, что он делает.
Возможно, ${parameter+word}
недокументированный альтернативный (или устаревший) синтаксис для ${parameter:+word}
? Может ли кто-нибудь подтвердить эту гипотезу?
Ответы:
Это для совместимости с оболочкой Bourne. Оболочка Bourne была старой оболочкой, которая была впервые выпущена с версией 7 Unix в 1979 году и до середины 90-х годов была распространена, как и
/bin/sh
в большинстве коммерческих Unices.Это является предком большинства Bourne-подобных оболочек , как
ksh
,bash
илиzsh
.У него было несколько неловких особенностей, многие из которых были исправлены в
ksh
других оболочках, и новая стандартная спецификацияsh
, одна из которых такова:С оболочкой Bourne (по крайней мере, в тех вариантах, где она не была исправлена):
"$@"
расширяется до одного пустого аргумента, если список позиционных параметров пуст ($# == 0
), а не аргумент вообще.${var+something}
расширяется до «чего-то», если$var
не установлено. Он четко задокументирован во всех оболочках, но его трудно найти вbash
документации, так как вам нужно обратить внимание на это предложение:Так
${1+"$@"}
расширяется,"$@"
только если$1
set ($# > 0
), который работает вокруг этого ограничения оболочки Bourne.Обратите внимание, что оболочка Bourne - единственная оболочка с этой проблемой. Современные
sh
s (которыеsh
соответствуют спецификации POSIXsh
(которой не является оболочка Bourne)) не имеют такой проблемы. Таким образом, вам нужно только, если вам нужен код для работы на очень старых системах, где/bin/sh
может быть оболочка Борна вместо стандартной оболочки (обратите внимание, что POSIX не указывает местоположение стандартаsh
, например, в Solaris до Solaris 11,/bin/sh
была все еще оболочкой Bourne (хотя у нее не было этой конкретной проблемы), в то время как normal / standardsh
находился в другом месте (/usr/xpg4/bin/sh
)).В этой
perlrun
странице perldoc есть проблема, которая$0
не указана.Смотрите http://www.in-ulm.de/~mascheck/various/bourne_args/ для получения дополнительной информации.
источник
Есть разница между:
а также
В одном вы передаете один аргумент, который является пустой строкой. Во втором случае передается ноль аргументов.
Для обоих, «$ @» будет приравнивать к тому же:
""
. Но использование${1:+"$@"}
будет""
для первого, и никакие аргументы не будут переданы для второго, что и было намерением.Это становится важным, если вы делаете что-то из приведенного ниже сценария, называемое sshwrapper, которое вы вызываете с помощью необязательной команды или без аргументов для получения интерактивной оболочки.
Это попыталось бы запустить "" на удаленном хосте (который просто возвращается), это не будет интерактивная оболочка.
Запустил бы интерактивную оболочку на удаленном хосте, потому что exec правильно интерпретировал бы переменную как ничто, а не пустую строку.
Прочтите об использовании "$ {параметр: + слово}" ("Использовать альтернативное значение") и подобных строк расширения переменных на страницах справки bash.
источник
sh
реализации, соответствующей POSIX (см. другой ответ).${1:+"$@"}
расширился бы без аргументов, если бы$1
был пустым. Вы хотите${1+"$@"}
. В основном у вас все наоборот.Я резюмировал ответ Стефана Шазеля:
так что если использовать вторую с параметром "", это означает, что $ 1 равен нулю, но он не проверяет, является ли он нулевым или нет, он просто видит, что он уже установлен, тем не менее, он пустой или нет, поэтому он будет расширять $ @ , но вы используете $ {1: + "$ @"} 'с "", он больше не будет расширяться
$@
.источник