Perlのドキュメントでは、 perlrun(1) は、バイリンガルのShell/Perlヘッダーを使用してPerlスクリプトを起動することを提案しています。
#!/bin/sh
#! -*-Perl-*-
eval 'exec Perl -x -wS $0 ${1+"$@"}'
if 0;
${1+"$@"}
の意味?代わりに"$@"
を使用してみました(/ bin/shとしてBashを使用)。これも同様に機能するようです。
以下の2つの回答は、それが${1:+"$@"}
であると想定していることを示しています。 bash(1)に記載されている${parameter:+Word}
( "代替値の使用")構文を知っています。しかし、私は納得できません。
パラメータがない場合でも、${1+"$@"}
と"$@"
はどちらも問題なく機能します。 simple.shを次のように作成した場合
#!/bin/sh
eval 'exec /usr/bin/Perl -x -S -- $0 "$@"'
if 0;
#!Perl
use Data::Dumper;
print Dumper(\@ARGV);
そしてquestion.shとして
#!/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+"$@"}
を使用します。これには one hacker が含まれます。
おそらく${parameter+Word}
は、文書化されていない代替(または非推奨)構文であり、${parameter:+Word}
?誰かがその仮説を確認できますか?
これは、Bourne Shellとの互換性のためです。 Bourne Shellは、1979年にUnixバージョン7で最初にリリースされた古いシェルで、90年代半ばまでほとんどの商用Unicesで/bin/sh
として一般的でした。
これは、ksh
、bash
、zsh
のようなほとんどのBourne-like shellsの祖先です。
いくつかの厄介な機能があり、その多くはksh
と他のシェルで修正されており、sh
の新しい標準仕様は次のとおりです。
Bourne Shell(少なくとも修正されていないバリアント)の場合:位置パラメータのリストが引数なしではなく空("$@"
)の場合、$# == 0
は1つの空の引数に展開されます。
${var+something}
が未設定でない限り、$var
は「何か」に展開されます。これはすべてのシェルで明確に文書化されていますが、この文に注意を払う必要があるため、bash
のドキュメントで見つけるのは困難です。
以下に記載されているフォームを使用して部分文字列展開を実行しない場合、bashは未設定またはnullのパラメーターをテストします。 コロンを省略すると、設定されていないパラメーターに対してのみテストが実行されます。
したがって、${1+"$@"}
は、"$@"
が設定されている場合にのみ$1
に展開されます($# > 0
)。これは、Bourne Shellの制限を回避します。
Bourne Shellがその問題を持つ唯一のShellであることに注意してください。最近のsh
s(つまり、sh
のPOSIX仕様に準拠しているsh
(これはBourne Shellにはありません))には、この問題はありません。したがって、/bin/sh
が標準シェルではなくBourneシェルである可能性がある非常に古いシステムでコードを動作させる必要がある場合にのみ必要です(POSIXは標準sh
の場所を指定していないため、たとえばSolaris 11より前のSolarisでは、/bin/sh
は依然としてBourneシェルでしたが(特定の問題はありませんでした)、通常/標準のsh
は別の場所(/usr/xpg4/bin/sh
))にありました。
ただし、$0
が引用されていないperlrun
perldocページに問題があります。
詳細は http://www.in-ulm.de/~mascheck/various/bourne_args/ を参照してください。
違いがあります:
command ""
そして
command
1つは、空の文字列である1つの引数を渡しています。 2番目には、渡される引数はありません。
どちらの場合も、「$ @」は同じものと同等です:""
。しかし、${1:+"$@"}
だろう ""
は最初の引数で、2番目の引数は渡されませんでした。
これは、sshwrapperと呼ばれる以下のスクリプトを実行する場合に重要になります。sshwrapperは、オプションのコマンドを使用して呼び出すか、引数なしで呼び出して、対話型シェルを取得します。
: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" "$@"
これは、リモートホスト( "戻る"のみ)で ""を実行しようとしますが、対話型シェルではありません。
: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" ${1:+"$@"}
Execは変数を空の文字列ではなく、何もないものとして正しく解釈するため、リモートホストでインタラクティブシェルを起動します。
"$ {parameter:+ Word}"( "Use Alternate Value")と同様の変数展開文字列の使用法については、bashのマニュアルページをご覧ください。
StéphaneChazelasの回答をまとめました。
したがって、パラメーター「」で2番目のパラメーターを使用すると、$ 1がnullであることを意味しますが、nullであるかどうかはテストされません。すでに設定されているにもかかわらず、空であるかどうかが確認されるため、$ @が展開されます。 、ただし$ {1:+ "$ @"} 'と ""を一緒に使用すると、展開されません$@
もう。