によるとman perlrun
:
-0[octal/hexadecimal]
specifies the input record separator ($/) as an octal or
hexadecimal number. If there are no digits, the null character is
the separator.
そして
The special value 00 will cause Perl to slurp files in paragraph
mode. Any value 0400 or above will cause Perl to slurp files
whole, but by convention the value 0777 is the one normally used
for this purpose.
ただし、次の入力ファイルが与えられた場合:
This is paragraph one
This is paragraph two.
予期しない結果が出ました。
$ perl -0ne 'print; exit' file ## \0 is used, so everything is printed
This is paragraph one.
This is paragraph two.
$ perl -00ne 'print; exit' file ## Paragraph mode, as expected
This is paragraph one.
今まではそんなに良くなった。今、これらの2つが短絡モードでも機能しているように見えるのはなぜですか?
$ perl -000ne 'print; exit' file
This is paragraph one.
$ perl -0000ne 'print; exit' file
This is paragraph one.
なぜこれがファイル全体を再び食べたと思いますか?
$ perl -00000ne 'print; exit' file
This is paragraph one.
This is paragraph two.
さらなるテストは、これらすべてが短絡モードで動作することを示した。
perl -000
perl -0000
perl -000000
perl -0000000
perl -00000000
たとえこれらがファイル全体を食べるように見えますが:
perl -00000
perl -000000000
私の問題は、私が8進数を十分に理解していないことです(実際に)。私はプログラマーではなく、生物学者です。と?0000
両方とも00000000
2つがファイル全体を食べますか>= 0400
?それともまったく異なることが起こっていますか?
答え1
8進数は、10進数と同様に、0 == 0、0000 == 0、0 == 000000などです。実際、ここのスイッチは-0
状況をやや混乱させる可能性があります。 「特殊値00」のポイントは、スイッチに対して1つのゼロを意味し、数値に0を追加しても変更されないことを意味すると仮定します。後者なので、同じ結果が得られます...
ある程度。などは000000
少しエラーのように動作しますが、これは以下を参照する必要があることを覚えておいてください。単一の8ビット値。 8ビットの範囲は10進数で0~255、8進数で0~377です。したがって、ここでは3桁以上の数字を使用できません(特殊値はすべてその範囲外ですが、まだ3桁+スイッチ)。以下からこれを推論できます。
16進表記(-0xHHH ...)を使用して区切り文字を指定することもできます。ここで、Hは有効な16進数です。8進形式とは異なりこれは、すべてのUnicode文字を指定するために使用できます。0xFFを超える値でも。
0xFF Hex == 255 Decimal == 377 Octal == (拡張) ASCII セットの 1 バイトおよび 1 文字サイズである最大 8 ビットです。
答え2
perl
詳細については、ソースコードを見てみましょう。存在するperl.c:
case '0':
{
I32 flags = 0;
STRLEN numlen;
SvREFCNT_dec(PL_rs);
if (s[1] == 'x' && s[2]) {
const char *e = s+=2;
U8 *tmps;
while (*e)
e++;
numlen = e - s;
flags = PERL_SCAN_SILENT_ILLDIGIT;
rschar = (U32)grok_hex(s, &numlen, &flags, NULL);
if (s + numlen < e) {
rschar = 0; /* Grandfather -0xFOO as -0 -xFOO. */
numlen = 0;
s--;
}
PL_rs = newSVpvs("");
SvGROW(PL_rs, (STRLEN)(UNISKIP(rschar) + 1));
tmps = (U8*)SvPVX(PL_rs);
uvchr_to_utf8(tmps, rschar);
SvCUR_set(PL_rs, UNISKIP(rschar));
SvUTF8_on(PL_rs);
}
else {
numlen = 4;
rschar = (U32)grok_oct(s, &numlen, &flags, NULL);
if (rschar & ~((U8)~0))
PL_rs = &PL_sv_undef;
else if (!rschar && numlen >= 2)
PL_rs = newSVpvs("");
else {
char ch = (char)rschar;
PL_rs = newSVpvn(&ch, 1);
}
}
sv_setsv(get_sv("/", GV_ADD), PL_rs);
return s + numlen;
}
グロンク_August8進数を表す文字列を数値形式に変換します。無効な8進数を入力しようとすると、すぐに返されます。すべての4文字(numlen = 4)が有効な値であると仮定します(実装ではforループを見ることができます)。数値.c)
したがって、-00000
最初の項目は解析され、にperl
設定されます。最後の項目が考慮され、リセットされます。以下で見ることができます:-0000
$/
\000
0
perl -0
$/
\000
$ perl -MO=Deparse -00000777ne 'print; exit' file
BEGIN { $/ = undef; $\ = undef; }
LINE: while (defined($_ = <ARGV>)) {
print $_;
exit;
}
-e syntax OK
$/
undef
最後に解析された8進数シーケンスがあっperl
たので、銀に設定されました0777
。
より明確に言えば:
$ perl -MO=Deparse -00000x1FF -ne 'print; exit' file
BEGIN { $/ = "\x{1ff}"; $\ = undef; }
LINE: while (defined($_ = <ARGV>)) {
print $_;
exit;
}
-e syntax OK
$/
最後の4桁の順序が設定されていることを確認できます0x1FF
。