素早い回答
シェルの見積もり処理は、すべて1つの引数であると考えているものを折りたたんで連結します。あなたの呼び出しは同等です
$ perl '-ienext unless /g/i'
perlはこの引数を含むものとして解析するため、すぐに中止され-u
ます。これにより、コードの実行が開始されるコアダンプがトリガーされます。これは、かつて疑似実行可能ファイルを作成するために使用されていた古い機能ですが、最近では本質的に痕跡的です。
の呼び出しのように見えるeval
のは、の誤解析です-e 'ss /g/i'
。
最初の手がかり
B ::サポートなしでシステムを実行している場合は、友達を解凍できますdump
。
$ echo 1 | perl -MO=Deparse,-p -ie'next unless /g/i'
dump is not supported.
BEGIN { $^I = "enext"; }
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined(($_ = <ARGV>))) {
chomp($_);
(('ss' / 'g') / 'i');
}
では、なぜunle
消えるのですか?Linuxを実行している場合は、私が行ったほどには到達していない可能性があります。上記の出力はCygwin上のPerlからのものであり、dump
サポートされていないことに関するエラーが手がかりです。
次の手がかり
perlrunのドキュメントからの注目:
-u
このスイッチにより、プログラムのコンパイル後にPerlがコアダンプします。次に、理論的には、このコアダンプを取得し、アンダンププログラム(提供されていません)を使用して実行可能ファイルに変換できます。これにより、ディスク容量をいくらか犠牲にして起動が高速化されます(実行可能ファイルを削除することで最小限に抑えることができます)。(それでも、「helloworld」実行可能ファイルは私のマシンでは約200Kになります。)ダンプする前にプログラムの一部を実行する場合は、dump
代わりに演算子を使用してください。注:アンダンプの可用性はプラットフォーム固有であり、Perlの特定のポートでは利用できない場合があります。
作業仮説と確認
Perlの引数処理では、チャンク全体がダッシュで始まるため、オプションの単一クラスターと見なされます。処理の実装でわかるように、この-i
オプションは次の単語()を消費します。enext
-i
case 'i':
Safefree(PL_inplace);
[Cygwin-specific code elided -geb]
{
const char * const start = ++s;
while (*s && !isSPACE(*s))
++s;
PL_inplace = savepvn(start, s - start);
}
if (*s) {
++s;
if (*s == '-') /* Additional switches on #! line. */
s++;
}
return s;
バックアップファイルの拡張子については、上記のperl.cのコードは、最初の空白文字または文字列の終わりのいずれか早い方までを消費します。文字が残っている場合は、最初の文字を空白にしてからスキップし、次の文字がダッシュの場合もスキップします。Perlでは、このロジックを次のように記述できます。
if ($$s =~ s/i(\S+)(?:\s-)//) {
my $extension = $1;
return $extension;
}
次に、、、、およびのすべて-u
が有効-n
なPerlオプションであるため、引数処理はそれらを食べて無意味なままにします-l
-e
ss /g/i
の引数として、-e
perlは一連の除算として解析します。しかし、実行が始まる前に、古語法-u
はperlにコアダンプを引き起こします。
意図しない動作
さらに奇妙なのは、との間に2つのスペースを入れる場合ですnext
。unless
$ perl -ie'next unless /g/i'
プログラムは実行を試みます。メインのオプション処理ループに戻ります。
case '*':
case ' ':
while( *s == ' ' )
++s;
if (s[0] == '-') /* Additional switches on #! line. */
return s+1;
break;
余分なスペースは、その引数のオプション解析を終了します。目撃者:
$ perl-ie'次のナンセンス-garbage--foo'-e die
-e行1で死亡しました。
しかし、余分なスペースがなければ、
$ perl-ie'次のナンセンス-garbage--foo'-e die
認識されないスイッチ:-onsense -garbage --foo(-hは有効なオプションを表示します)。
ただし、余分なスペースとダッシュがあります
$ perl -ie'next -unless / g / i'
ダンプはサポートされていません。
デザインの動機
コメントが示すように、ロジックは厳しいシバン(#!
)行制約のためにあり、perlは回避するために最善を尽くします。
インタプリタスクリプト
インタプリタスクリプトは、実行権限が有効になっていて、最初の行が次の形式のテキストファイルです。
#! interpreter [optional-arg]
インタプリタは、それ自体がスクリプトではない実行可能ファイルの有効なパス名である必要があります。のfilename引数がexecve
インタプリタスクリプトを指定している場合、インタプリタは次の引数で呼び出されます。
interpreter [optional-arg] filename arg...
ここで、arg ...は、。のargv
引数が指す一連の単語ですexecve
。
ポータブルで使用する場合、optional-argは存在しないか、単一の単語として指定する必要があります(つまり、空白を含めることはできません)…</ p>