来自 man perlre
:
The "*" quantifier is equivalent to "{0,}", the "+" quantifier to "{1,}", and the "?" quantifier to "{0,1}". n and m are limited to integral values less than a preset limit defined when perl is built. This is usually 32766 on the most common platforms. The actual limit can be seen in the error message generated by code such as this:
$_ **= $_ , / {$_} / for 2 .. 42;
是的,这很丑 - 不是有一些我可以得到的常数吗?
编辑:正如 daxim 指出的(和 perlretut 暗示的),32767 可能是一个神奇的硬编码数字。一点searching在 Perl 代码中有很长的路要走,但我不确定如何进行下一步并实际找出默认的 reg_infty 或 REG_INFTY 实际设置的位置:
~/dev/perl-5.12.2
$ grep -ri 'reg_infty.*=' *
regexec.c: if (max != REG_INFTY && ST.count == max)
t/re/pat.t: $::reg_infty = $Config {reg_infty} // 32767;
t/re/pat.t: $::reg_infty_m = $::reg_infty - 1;
t/re/pat.t: $::reg_infty_p = $::reg_infty + 1;
t/re/pat.t: $::reg_infty_m = $::reg_infty_m; # Surpress warning.
编辑 2:DVK 当然是对的:它是
define
d 在编译时,并且可能只能用 REG_INFTY
覆盖.
最佳答案
总结:我可以想到 3 种方法来找到极限:经验、“匹配 Perl 测试”和“理论”。
eval {$_ **= $_ , / {$_} / for 2 .. 129};
# To be truly portable, the above should ideally loop forever till $@ is true.
$@ =~ /bigger than (-?\d+) /;
print "LIMIT: $1\n"'
这似乎很明显,不需要解释。
Perl 对正则表达式进行了一系列测试,其中一些(在
pat.t
中)处理测试这个最大值。因此,您可以近似认为这些测试中计算出的最大值“足够好”并遵循测试逻辑:use Config;
$reg_infty = $Config {reg_infty} // 2 ** 15 - 1; # 32767
print "Test-based reg_infinity limit: $reg_infty\n";
在测试中这是基于何处的解释在下面的详细信息中。
这听起来更难,因为它受到两件事的影响:Perl 构建配置和一堆带有分支逻辑的 C
#define
语句。我能够深入研究该逻辑,但在两个问题上停滞不前:#ifdefs
引用了一堆实际上没有在我可以找到的 Perl 代码中定义的标记 - 我不知道如何从中找出在 Perl 中,那些 define
的值是什么,以及最终的默认值(假设我是对的,而那些 #ifdef
总是以默认值结束)为 #define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)
(实际限制是通过从结果全1 数中删除 1 位来获得的- 详情如下)。我也不确定如何从 Perl 访问
short
中的字节量,无论使用哪种实现来构建 perl
可执行文件。因此,即使可以找到这两个问题的答案(我不确定),结果逻辑肯定会比我提供的简单的“基于经验的评估”逻辑更“丑陋”和更复杂。第一个选项。
下面我将详细说明与此限制相关的各种逻辑在 Perl 代码中的位置,以及我尝试得出与 C 逻辑匹配的“理论上正确”的解决方案。
好的,这是部分调查,您可以自己完成,因为我正在运行,或者我稍后会完成:
regcomp.c
: vFAIL2("Quantifier in {,} bigger than %d", REG_INFTY - 1);
因此,该限制显然取自
REG_INFTY
定义。声明在:rehcomp.h
: /* XXX fix this description.
Impose a limit of REG_INFTY on various pattern matching operations
to limit stack growth and to avoid "infinite" recursions.
*/
/* The default size for REG_INFTY is I16_MAX, which is the same as
SHORT_MAX (see perl.h). Unfortunately I16 isn't necessarily 16 bits
(see handy.h). On the Cray C90, sizeof(short)==4 and hence I16_MAX is
((1<<31)-1), while on the Cray T90, sizeof(short)==8 and I16_MAX is
((1<<63)-1). To limit stack growth to reasonable sizes, supply a
smaller default.
--Andy Dougherty 11 June 1998
*/
#if SHORTSIZE > 2
# ifndef REG_INFTY
# define REG_INFTY ((1<<15)-1)
# endif
#endif
#ifndef REG_INFTY
# define REG_INFTY I16_MAX
#endif
请注意,SHORTSIZE 可通过
Config
覆盖 - 我将省略详细信息,但逻辑需要包括 $Config{shortsize}
:) #if defined(UINT8_MAX) && defined(INT16_MAX) && defined(INT32_MAX)
#define I16_MAX INT16_MAX
#else
#define I16_MAX PERL_SHORT_MAX
INT16_MAX
的 任何 地方:(有人帮忙请!!!
#ifdef SHORT_MAX
# define PERL_SHORT_MAX ((short)SHORT_MAX)
#else
# ifdef MAXSHORT /* Often used in <values.h> */
# define PERL_SHORT_MAX ((short)MAXSHORT)
# else
# ifdef SHRT_MAX
# define PERL_SHORT_MAX ((short)SHRT_MAX)
# else
# define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1))
# endif
# endif
#endif
到目前为止,我找不到任何定义 SHORT_MAX、MAXSHORT 或 SHRT_MAX 的地方。所以默认的
((short) (PERL_USHORT_MAX >> 1))
假设现在是 :) perl.h
中的定义非常相似,我再次找不到 USHORT_MAX
/MAXUSHORT
/USHRT_MAX
的定义痕迹。这似乎暗示它默认设置为:
#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)
。如何从 Perl 端提取该值,我不知道 - 它基本上是通过按位取反短 0 得到的数字,所以如果 unsigned short 是 16 个字节,那么 PERL_USHORT_MAX
将是 16 个,而 PERL_SHORT_MAX
将是 15 个,例如2^15-1,例如32767. t/re/pat.t
(正则表达式测试):$::reg_infty = $Config {reg_infty} // 32767;
(说明非默认编译值的存储位置)。 所以,为了得到你的常数,你做:
use Config;
my $shortsize = $Config{shortsize} // 2;
$c_reg_infty = (defined $Config {reg_infty}) ? $Config {reg_infty}
: ($shortsize > 2) ? 2**16-1
: get_PERL_SHORT_MAX();
# Where get_PERL_SHORT_MAX() depends on logic for PERL_SHORT_MAX in perl.h
# which I'm not sure how to extract into Perl with any precision
# due to a bunch of never-seen "#define"s and unknown size of "short".
# You can probably do fairly well by simply returning 2**8-1 if shortsize==1
# and 2^^16-1 otherwise.
say "REAL reg_infinity based on C headers: $c_reg_infty";
关于perlre 长度限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4592467/