内容

名称

perlreapi - Perl 正则表达式插件接口

描述

从 Perl 5.9.5 开始,提供了一种新的接口,用于插入和使用除默认正则表达式引擎之外的其他引擎。

每个引擎都应该提供对以下格式的常量结构的访问

    typedef struct regexp_engine {
        REGEXP* (*comp) (pTHX_
                         const SV * const pattern, const U32 flags);
        I32     (*exec) (pTHX_
                         REGEXP * const rx,
                         char* stringarg,
                         char* strend, char* strbeg,
                         SSize_t minend, SV* sv,
                         void* data, U32 flags);
        char*   (*intuit) (pTHX_
                           REGEXP * const rx, SV *sv,
			   const char * const strbeg,
                           char *strpos, char *strend, U32 flags,
                           struct re_scream_pos_data_s *data);
        SV*     (*checkstr) (pTHX_ REGEXP * const rx);
        void    (*free) (pTHX_ REGEXP * const rx);
        void    (*numbered_buff_FETCH) (pTHX_
                                        REGEXP * const rx,
                                        const I32 paren,
                                        SV * const sv);
        void    (*numbered_buff_STORE) (pTHX_
                                        REGEXP * const rx,
                                        const I32 paren,
                                        SV const * const value);
        I32     (*numbered_buff_LENGTH) (pTHX_
                                         REGEXP * const rx,
                                         const SV * const sv,
                                         const I32 paren);
        SV*     (*named_buff) (pTHX_
                               REGEXP * const rx,
                               SV * const key,
                               SV * const value,
                               U32 flags);
        SV*     (*named_buff_iter) (pTHX_
                                    REGEXP * const rx,
                                    const SV * const lastkey,
                                    const U32 flags);
        SV*     (*qr_package)(pTHX_ REGEXP * const rx);
    #ifdef USE_ITHREADS
        void*   (*dupe) (pTHX_ REGEXP * const rx, CLONE_PARAMS *param);
    #endif
        REGEXP* (*op_comp) (...);

当正则表达式被编译时,它的engine字段会被设置为指向相应的结构,这样当需要使用它时,Perl 就可以找到正确的例程来执行。

为了安装新的正则表达式处理程序,$^H{regcomp} 被设置为一个整数,该整数(在适当的类型转换后)解析为这些结构之一。在编译时,comp 方法被执行,并且生成的 regexp 结构的 engine 字段应该指向同一个结构。

定义中的 pTHX_ 符号是 Perl 在多线程环境下使用的宏,用于向例程提供一个额外的参数,该参数指向正在执行正则表达式的解释器。因此,在多线程环境下,所有例程都会获得一个额外的参数。

回调

comp

REGEXP* comp(pTHX_ const SV * const pattern, const U32 flags);

使用给定的 flags 编译存储在 pattern 中的模式,并返回指向已准备好的 REGEXP 结构的指针,该结构可以执行匹配。有关 REGEXP 结构中各个字段的说明,请参见下面的 "REGEXP 结构"

pattern 参数是作为模式使用的标量。Perl 的早期版本会传递两个 char*,分别表示字符串化模式的开始和结束;可以使用以下代码段获取旧的参数

STRLEN plen;
char*  exp = SvPV(pattern, plen);
char* xend = exp + plen;

由于任何标量都可以作为模式传递,因此可以实现一个引擎,该引擎对数组("ook" =~ [ qw/ eek hlagh / ])或编译正则表达式的非字符串化形式("ook" =~ qr/eek/)执行某些操作。Perl 自身的引擎总是使用上面的代码段将所有内容字符串化,但这并不意味着其他引擎也必须这样做。

flags 参数是一个位域,它指示正则表达式是用哪些 msixpn 标志编译的。它还包含其他信息,例如 use locale 是否生效。

eogc 标志在传递给 comp 例程之前会被剥离。正则表达式引擎不需要知道是否设置了这些标志,因为这些标志应该只影响 Perl 对模式及其匹配变量的操作,而不是影响它的编译和执行方式。

在调用 comp 回调之前,其中一些标志已经生效(在适用的地方进行了说明)。但是,它们的大部分影响是在 comp 回调运行之后发生的,在读取 rx->extflags 字段的例程中,该字段由它填充。

通常情况下,标志应该在编译后保留在rx->extflags中,尽管正则表达式引擎可能需要添加或删除一些标志来调用或禁用 Perl 中的一些特殊行为。标志及其导致的任何特殊行为将在下面进行说明。

模式修饰符

/m - RXf_PMf_MULTILINE

如果此标志存在于rx->extflags中,它将由pp_split传递给Perl_fbm_instr,后者将把目标字符串视为多行字符串。

/s - RXf_PMf_SINGLELINE
/i - RXf_PMf_FOLD
/x - RXf_PMf_EXTENDED

如果在正则表达式中存在,"#" 注释在某些情况下将由词法分析器以不同的方式处理。

待办事项:记录这些情况。

/p - RXf_PMf_KEEPCOPY

待办事项:记录此标志。

字符集

字符集规则由此字段中包含的枚举确定。这仍然是实验性的,可能会发生变化,但当前接口使用内联函数get_regex_charset(const U32 flags)返回规则。目前唯一记录的返回值是 REGEX_LOCALE_CHARSET,如果use locale生效,则会设置此值。如果存在于rx->extflags中,split将在 RXf_SKIPWHITE 或 RXf_WHITE 生效时使用与区域设置相关的空格定义。ASCII 空格定义为根据isSPACE,以及在 UTF-8 下的内部宏is_utf8_space,以及在use locale下的isSPACE_LC

其他标志

RXf_SPLIT

此标志已在 perl 5.18.0 中移除。split ' ' 现在仅在解析器中被特殊处理。RXf_SPLIT 仍然被 #defined,因此您可以测试它。以下是它以前的工作方式

如果split被调用为split ' '或没有参数(实际上意味着split(' ', $_),请参阅split),Perl 将设置此标志。然后正则表达式引擎可以检查它并设置 SKIPWHITE 和 WHITE 扩展标志。为此,Perl 引擎执行以下操作

if (flags & RXf_SPLIT && r->prelen == 1 && r->precomp[0] == ' ')
    r->extflags |= (RXf_SKIPWHITE|RXf_WHITE);

这些标志可以在编译期间设置,以在split操作符中启用优化。

RXf_SKIPWHITE

此标志在 Perl 5.18.0 中已被移除。它仍然被 #defined,因此您可以设置它,但这样做不会有任何效果。以下是它以前的工作方式

如果该标志存在于 rx->extflags 中,split 将在操作之前从目标字符串的开头删除空格。空格的定义取决于目标字符串是否为 UTF-8 字符串以及是否设置了 RXf_PMf_LOCALE 标志。

如果除了此标志之外还设置了 RXf_WHITE,split 的行为将类似于 Perl 引擎下的 split " "

RXf_START_ONLY

告诉 split 操作符在换行符 (\n) 上分割目标字符串,而无需调用正则表达式引擎。

如果模式为 /^/ (plen == 1 && *exp == '^'),即使在 /^/s 下,Perl 引擎也会设置此标志;请参阅 split。当然,不同的正则表达式引擎可能希望使用不同的语法来实现相同的优化。

RXf_WHITE

告诉 split 操作符在空格上分割目标字符串,而无需调用正则表达式引擎。空格的定义取决于目标字符串是否为 UTF-8 字符串以及是否设置了 RXf_PMf_LOCALE。

如果模式为 \s+,Perl 引擎将设置此标志。

RXf_NULL

告诉 split 操作符在字符上分割目标字符串。字符的定义取决于目标字符串是否为 UTF-8 字符串。

Perl 引擎在空模式下设置此标志,此优化使 split // 比其他方式快得多。它甚至比 unpack 更快。

RXf_NO_INPLACE_SUBST

在 Perl 5.18.0 中添加,此标志表示正则表达式可能会执行与就地替换冲突的操作。例如,它可能包含后顾,或在匹配期间分配给非魔术变量(例如 $REGMARK 和 $REGERROR)。s/// 在设置此标志时将跳过某些优化。

exec

I32 exec(pTHX_ REGEXP * const rx,
         char *stringarg, char* strend, char* strbeg,
         SSize_t minend, SV* sv,
         void* data, U32 flags);

执行正则表达式。参数为

rx

要执行的正则表达式。

sv

这是要匹配的 SV。请注意,实际要匹配的字符数组由下面描述的参数提供;SV 仅用于确定 UTF8 性质、pos() 等。

strbeg

指向字符串物理起始位置的指针。

strend

指向字符串物理结束位置后的字符的指针(即 \0,如果有的话)。

stringarg

指向字符串中应开始匹配的位置的指针;它可能不等于 strbeg(例如在 /.../g 的后续迭代中)。

minend

字符串的最小长度(以从 stringarg 开始的字节数衡量),必须匹配;如果引擎到达匹配的末尾但尚未到达字符串中的此位置,则应失败。

data

优化数据;可能会发生变化。

flags

优化标志;可能会发生变化。

intuit

    char* intuit(pTHX_
		REGEXP * const rx,
		SV *sv,
		const char * const strbeg,
		char *strpos,
		char *strend,
		const U32 flags,
		struct re_scream_pos_data_s *data);

找到应尝试进行正则表达式匹配的起始位置,或者如果正则表达式引擎不应该运行因为模式无法匹配,则可能找到该位置。根据 regexp 结构的 extflags 成员的值,核心会适当地调用它。

参数

    rx:     the regex to match against
    sv:     the SV being matched: only used for utf8 flag; the string
	    itself is accessed via the pointers below. Note that on
	    something like an overloaded SV, SvPOK(sv) may be false
	    and the string pointers may point to something unrelated to
	    the SV itself.
    strbeg: real beginning of string
    strpos: the point in the string at which to begin matching
    strend: pointer to the byte following the last char of the string
    flags   currently unused; set to 0
    data:   currently unused; set to NULL

checkstr

SV*	checkstr(pTHX_ REGEXP * const rx);

返回一个包含必须出现在模式中的字符串的 SV。由 split 用于优化匹配。

free

void free(pTHX_ REGEXP * const rx);

当 Perl 释放正则表达式模式时,Perl 会调用它,以便引擎可以释放 regexp 结构的 pprivate 成员指向的任何资源。这仅负责释放私有数据;Perl 将负责释放 regexp 结构中包含的任何其他内容。

编号捕获回调

用于获取/设置 $`$'$& 及其命名等效项的值,即 ${^PREMATCH}、${^POSTMATCH} 和 ${^MATCH},以及编号捕获组($1$2、...)。

paren 参数对于 $11,对于 $22,依此类推,并且对于特殊变量具有以下符号值

${^PREMATCH}  RX_BUFF_IDX_CARET_PREMATCH
${^POSTMATCH} RX_BUFF_IDX_CARET_POSTMATCH
${^MATCH}     RX_BUFF_IDX_CARET_FULLMATCH
$`            RX_BUFF_IDX_PREMATCH
$'            RX_BUFF_IDX_POSTMATCH
$&            RX_BUFF_IDX_FULLMATCH

请注意,在 Perl 5.17.3 及更早版本中,最后三个常量也用于变量的插入符号变体。

这些名称是根据 Tie::Scalar 方法名称类推选择的,并添加了 LENGTH 回调以提高效率。但是,命名捕获变量目前没有在内部绑定,而是通过魔术实现的。

numbered_buff_FETCH

void numbered_buff_FETCH(pTHX_ REGEXP * const rx, const I32 paren,
                         SV * const sv);

获取指定编号的捕获。sv 应该设置为要返回的标量,标量作为参数传递而不是从函数返回,因为当它被调用时,Perl 已经有一个标量来存储值,创建另一个标量将是多余的。标量可以使用 sv_setsvsv_setpvn 等设置,请参见 perlapi

此回调是在 Perl 在 taint 模式下解除自身捕获变量的 taint 时(参见 perlsec)。有关如何在 taint 模式下解除捕获变量的 taint,请参见 regcomp.c 中的 Perl_reg_numbered_buff_fetch 函数,如果您希望您的引擎也执行此操作。

numbered_buff_STORE

void    (*numbered_buff_STORE) (pTHX_
                                REGEXP * const rx,
                                const I32 paren,
                                SV const * const value);

设置编号捕获变量的值。value 是将用作新值的标量。引擎需要确保将其用作新值(或拒绝它)。

示例

if ("ook" =~ /(o*)/) {
    # 'paren' will be '1' and 'value' will be 'ee'
    $1 =~ tr/o/e/;
}

Perl 自身的引擎将在任何尝试修改捕获变量的操作上抛出异常,要在另一个引擎中执行此操作,请使用以下回调(从 Perl_reg_numbered_buff_store 复制)

void
Example_reg_numbered_buff_store(pTHX_
                                REGEXP * const rx,
                                const I32 paren,
                                SV const * const value)
{
    PERL_UNUSED_ARG(rx);
    PERL_UNUSED_ARG(paren);
    PERL_UNUSED_ARG(value);

    if (!PL_localizing)
        Perl_croak(aTHX_ PL_no_modify);
}

实际上,Perl 不会总是在看起来会修改编号捕获变量的语句中抛出异常。这是因为如果 Perl 可以确定它不需要修改值,则不会调用 STORE 回调。这正是绑定变量在相同情况下表现的方式

package CaptureVar;
use parent 'Tie::Scalar';

sub TIESCALAR { bless [] }
sub FETCH { undef }
sub STORE { die "This doesn't get called" }

package main;

tie my $sv => "CaptureVar";
$sv =~ y/a/b/;

因为当 y/// 操作应用于 $sv 时,$svundef,所以转换实际上不会执行,程序也不会 die。这与 5.8 及更早版本的行为不同,因为捕获变量当时是 READONLY 变量;现在,它们在默认引擎中被赋值时只会 die

numbered_buff_LENGTH

I32 numbered_buff_LENGTH (pTHX_
                          REGEXP * const rx,
                          const SV * const sv,
                          const I32 paren);

获取捕获变量的 length。为此有一个特殊的回调,这样 Perl 不必执行 FETCH 并对结果运行 length,因为长度(在 Perl 的情况下)是从 rx->offs 中存储的偏移量中知道的,这效率更高

I32 s1  = rx->offs[paren].start;
I32 s2  = rx->offs[paren].end;
I32 len = t1 - s1;

在 UTF-8 的情况下,这会稍微复杂一些,请参见 Perl_reg_numbered_buff_length 使用 is_utf8_string_loclen 的方式。

命名捕获回调

用于获取/设置 %+%- 的值,以及 re 中的一些实用程序函数。

有两个回调函数,named_buff 在所有 FETCH、STORE、DELETE、CLEAR、EXISTS 和 SCALAR Tie::Hash 回调函数会被调用,这些回调函数会在对 %+%- 进行更改时被调用,而 named_buff_iter 则在与 FIRSTKEY 和 NEXTKEY 相同的情况下被调用。

flags 参数可以用来确定回调函数应该响应哪些操作。目前定义了以下标志:

从 Perl 层面对 %+%- 执行的 Tie::Hash 操作,如果有的话。

RXapif_FETCH
RXapif_STORE
RXapif_DELETE
RXapif_CLEAR
RXapif_EXISTS
RXapif_SCALAR
RXapif_FIRSTKEY
RXapif_NEXTKEY

如果对 %+%- 进行了操作,如果有的话。

RXapif_ONE /* %+ */
RXapif_ALL /* %- */

如果这是作为 re::regnamere::regnamesre::regnames_count 被调用,如果有的话。前两个将与 RXapif_ONERXapif_ALL 结合使用。

RXapif_REGNAME
RXapif_REGNAMES
RXapif_REGNAMES_COUNT

在内部,%+%- 是通过 Tie::Hash::NamedCapture 使用真正的绑定接口实现的。该包中的方法将回调到这些函数。但是,将 Tie::Hash::NamedCapture 用于此目的的方式可能会在将来的版本中发生变化。例如,这可以通过魔法来实现(需要对 mgvtbl 进行扩展)。

named_buff

SV*     (*named_buff) (pTHX_ REGEXP * const rx, SV * const key,
                       SV * const value, U32 flags);

named_buff_iter

SV*     (*named_buff_iter) (pTHX_
                            REGEXP * const rx,
                            const SV * const lastkey,
                            const U32 flags);

qr_package

SV* qr_package(pTHX_ REGEXP * const rx);

qr// 魔法对象被祝福到的包(如 ref qr// 所示)。建议引擎将此更改为其包名以进行识别,无论它们是否在对象上实现方法。

此方法返回的包也应该在其 @ISA 中包含内部 Regexp 包。qr//->isa("Regexp") 应该始终为真,无论使用哪个引擎。

示例实现可能是

SV*
Example_qr_package(pTHX_ REGEXP * const rx)
{
	PERL_UNUSED_ARG(rx);
	return newSVpvs("re::engine::Example");
}

对使用 qr// 创建的对象进行的任何方法调用都将作为普通对象分派到该包。

use re::engine::Example;
my $re = qr//;
$re->meth; # dispatched to re::engine::Example::meth()

要在 XS 函数中从标量中检索 REGEXP 对象,请使用 SvRX 宏,请参阅 "perlapi 中的 REGEXP 函数"

void meth(SV * rv)
PPCODE:
    REGEXP * re = SvRX(sv);

dupe

void* dupe(pTHX_ REGEXP * const rx, CLONE_PARAMS *param);

在多线程构建中,可能需要复制正则表达式,以便多个线程可以使用该模式。此例程预计会处理对 regexp 结构的 pprivate 成员指向的任何私有数据的复制。它将使用预先构建的新 regexp 结构作为参数调用,pprivate 成员将指向的私有结构,并且此例程的责任是构建一个副本并返回指向它的指针(Perl 将使用它来覆盖传递给此例程的字段)。

这允许引擎复制其私有数据,并且如果需要,还可以修改最终结构,如果它确实必须这样做。

在非多线程构建中,此字段不存在。

op_comp

这是 Perl 内核的私有内容,可能会发生变化。应保留为空。

REGEXP 结构

REGEXP 结构在 regexp.h 中定义。所有正则表达式引擎都必须能够在其 "comp" 例程中正确构建这样的结构。

REGEXP 结构包含 Perl 需要知道的所有数据,以便正确地使用正则表达式。它包括有关 Perl 可以用来确定是否应该真正使用正则表达式引擎的优化的数据,以及在各种上下文中正确执行模式所需的各种其他控制信息,例如模式是否以某种方式锚定,或者在编译期间使用了哪些标志,或者程序是否包含 Perl 需要知道的特殊结构。

此外,它还包含两个字段,用于编译模式的正则表达式引擎的私有使用。它们是 intflagspprivate 成员。pprivate 是指向任意结构的 void 指针,其使用和管理由编译引擎负责。Perl 永远不会修改这两个值中的任何一个。

    typedef struct regexp {
        /* what engine created this regexp? */
        const struct regexp_engine* engine;

        /* what re is this a lightweight copy of? */
        struct regexp* mother_re;

        /* Information about the match that the Perl core uses to manage
         * things */
        U32 extflags;   /* Flags used both externally and internally */
	I32 minlen;	/* mininum possible number of chars in */
                           string to match */
	I32 minlenret;	/* mininum possible number of chars in $& */
        U32 gofs;       /* chars left of pos that we search from */

        /* substring data about strings that must appear
           in the final match, used for optimisations */
        struct reg_substr_data *substrs;

        U32 nparens;  /* number of capture groups */

        /* private engine specific data */
        U32 intflags;   /* Engine Specific Internal flags */
        void *pprivate; /* Data private to the regex engine which 
                           created this object. */

        /* Data about the last/current match. These are modified during
         * matching*/
        U32 lastparen;            /* highest close paren matched ($+) */
        U32 lastcloseparen;       /* last close paren matched ($^N) */
        regexp_paren_pair *offs;  /* Array of offsets for (@-) and
                                     (@+) */

        char *subbeg;  /* saved or original string so \digit works
                          forever. */
        SV_SAVED_COPY  /* If non-NULL, SV which is COW from original */
        I32 sublen;    /* Length of string pointed by subbeg */
        I32 suboffset;	/* byte offset of subbeg from logical start of
                           str */
	I32 subcoffset;	/* suboffset equiv, but in chars (for @-/@+) */

        /* Information about the match that isn't often used */
        I32 prelen;           /* length of precomp */
        const char *precomp;  /* pre-compilation regular expression */

        char *wrapped;  /* wrapped version of the pattern */
        I32 wraplen;    /* length of wrapped */

        I32 seen_evals;   /* number of eval groups in the pattern - for
                             security checks */
        HV *paren_names;  /* Optional hash of paren names */

        /* Refcount of this regexp */
        I32 refcnt;             /* Refcount of this regexp */
    } regexp;

这些字段将在下面更详细地讨论。

engine

此字段指向一个 regexp_engine 结构,该结构包含指向用于执行匹配的子例程的指针。编译例程有责任在返回正则表达式对象之前填充此字段。

在内部,除非在 $^H{regcomp} 中指定了自定义引擎,否则它被设置为 NULL,Perl 自己的回调集可以在 RE_ENGINE_PTR 指向的结构中访问。

mother_re

待办事项,请参阅提交 28d8d7f41a。

extflags

Perl 将使用此字段来查看正则表达式编译时使用的标志,通常情况下,此字段将由 comp 回调函数设置为 flags 参数的值。有关有效标志,请参阅 comp 文档。

minlen minlenret

模式匹配所需的最小字符串长度(以字符为单位)。这用于修剪搜索空间,避免在字符串末尾进行匹配,因为这样做不会比允许匹配更接近字符串末尾。例如,如果 minlen 为 10 但字符串只有 5 个字符长,则没有必要启动正则表达式引擎。模式不可能匹配。

minlenret 是匹配后在 $& 中找到的字符串的最小长度(以字符为单位)。

以下模式可以看出 minlenminlenret 之间的区别

/ns(?=\d)/

其中 minlen 为 3,但 minlenret 仅为 2,因为 \d 需要匹配,但实际上不包含在匹配的内容中。这种区别尤其重要,因为替换逻辑使用 minlenret 来判断是否可以进行就地替换(这会导致速度大幅提升)。

gofs

从 pos() 开始匹配的左侧偏移量。

substrs

有关必须出现在最终匹配中的字符串的子字符串数据。目前,这仅在 Perl 引擎内部使用,但将来可能会用于所有引擎进行优化。

nparenslastparenlastcloseparen

这些字段用于跟踪:模式中包含多少个括号捕获组;哪个是最高级别的已关闭括号(请参阅 "$+" in perlvar);以及哪个是最新的已关闭括号(请参阅 "$^N" in perlvar)。

intflags

引擎对模式编译时使用的标志的私有副本。通常情况下,此字段与 extflags 相同,除非引擎选择修改其中一个标志。

pprivate

指向引擎定义的数据结构的 void*。Perl 引擎使用 regexp_internal 结构(请参阅 "Base Structures" in perlreguts),但自定义引擎应该使用其他结构。

offs

一个 regexp_paren_pair 结构,它定义了匹配字符串中的偏移量,这些偏移量对应于 $&$1$2 等捕获,regexp_paren_pair 结构定义如下:

typedef struct regexp_paren_pair {
    I32 start;
    I32 end;
} regexp_paren_pair;

如果 ->offs[num].start->offs[num].end-1,则该捕获组未匹配。->offs[0].start/end 代表 $&(或 ${^MATCH}/p 下),->offs[paren].end 匹配 $$paren,其中 $paren = 1>。

precomp prelen

用于优化。precomp 保存了编译后的模式的副本,prelen 是它的长度。当要编译一个新的模式(例如在循环中)时,内部 regcomp 运算符会检查最后一个编译的 REGEXPprecompprelen 是否与新的模式等效,如果是,则使用旧的模式而不是编译一个新的模式。

来自 Perl_pp_regcomp 的相关代码片段

	if (!re || !re->precomp || re->prelen != (I32)len ||
	    memNE(re->precomp, t, len))
        /* Compile a new pattern */

paren_names

这是一个内部用于跟踪命名捕获组及其偏移量的哈希表。键是缓冲区的名称,值是双变量,IV 槽位保存具有给定名称的缓冲区数量,pv 是一个嵌入的 I32 数组。当使用命名反向引用时,这些值也可以独立地包含在数据数组中。

substrs

保存有关必须从模式开头开始的固定偏移量处出现的最长字符串和必须从模式开头开始的浮动偏移量处出现的最长字符串的信息。用于对字符串进行快速 Boyer-Moore 搜索,以确定是否值得使用正则表达式引擎,以及如果值得,则在字符串的哪个位置进行搜索。

subbeg sublen saved_copy suboffset subcoffset

在执行阶段用于管理搜索和替换模式,以及提供 $&$1 等的文本。subbeg 指向一个缓冲区(原始字符串或 RX_MATCH_COPIED(rx) 情况下的副本),sublen 是缓冲区的长度。RX_OFFS 的开始和结束索引索引到此缓冲区。

如果设置了 REXEC_COPY_STR 标志,但同时设置了 REXEC_COPY_SKIP_PREREXEC_COPY_SKIP_POST 标志,引擎可以选择不复制整个缓冲区(尽管在 RXf_PMf_KEEPCOPY 设置或 PL_sawampersand 中设置了相关位的情况下,仍然必须复制)。在这种情况下,引擎可以设置 suboffset 来指示从缓冲区逻辑起始位置到物理起始位置的字节数(即 subbeg)。它还应该设置 subcoffset,即偏移量中的字符数。后者是支持 @-@+ 所必需的,因为它们以字符而不是字节为单位工作。

wrapped wraplen

存储字符串 qr// 转换为的字符串。例如,Perl 引擎在 qr/eek/ 的情况下存储 (?^:eek)

当使用不支持 (?:) 结构进行内联修饰符的自定义引擎时,最好让 qr// 转换为提供的模式,注意这将在以下情况下创建不希望的模式:

my $x = qr/a|b/;  # "a|b"
my $y = qr/c/i;   # "c"
my $z = qr/$x$y/; # "a|bc"

除了让自定义引擎理解类似 (?:) 的结构之外,没有其他解决方案可以解决这个问题。

seen_evals

它存储模式中 eval 组的数量。这在将编译后的正则表达式嵌入到使用 qr// 的更大模式中时用于安全目的。

refcnt

结构被引用的次数。当此值降至 0 时,正则表达式将通过调用 pregfree 自动释放。这应该在每个引擎的 "comp" 例程中设置为 1。

历史

最初是 perlreguts 的一部分。

作者

最初由 Yves Orton 编写,由 Ævar Arnfjörð Bjarmason 扩展。

许可证

版权所有 2006 Yves Orton 和 2007 Ævar Arnfjörð Bjarmason。

本程序是自由软件;您可以根据与 Perl 本身相同的条款重新分发和/或修改它。