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 在執行緒中使用,用來提供一個額外的引數給常式,持有回溯至執行正規表示式的直譯器的指標。因此,在執行緒中,所有常式都會取得一個額外的引數。
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
是否有效。
在傳遞給 comp 常式之前,會先移除 eogc
旗標。正規表示式引擎不需要知道是否設定了這些旗標,因為這些旗標只會影響 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` 中,當 RXf_SKIPWHITE 或 RXf_WHITE 有效時,`split` 會使用與區域設定相關的空白定義。ASCII 空白根據 isSPACE 以及 UTF-8 下的內部巨集 `is_utf8_space` 和 `use locale` 下的 `isSPACE_LC` 來定義。
其他旗標
此旗標已在 perl 5.18.0 中移除。現在 `split ' '` 僅在剖析器中為特殊情況。RXf_SPLIT 仍為 #defined,因此您可以測試它。以下是它的運作方式
如果 `split` 被呼叫為 `split ' '` 或沒有參數(這實際上表示 `split(' ', $_)`,請參閱 split),Perl 會設定此旗標。然後,正規表示式引擎可以檢查它並設定 SKIPWHITE 和 WHITE extflags。Perl 引擎會執行以下動作來執行此操作
if (flags & RXf_SPLIT && r->prelen == 1 && r->precomp[0] == ' ')
r->extflags |= (RXf_SKIPWHITE|RXf_WHITE);
可以在編譯期間設定這些旗標,以在 `split` 運算子中啟用最佳化。
此旗標已在 perl 5.18.0 中移除。它仍為 #defined,因此您可以設定它,但這樣做不會有任何效果。以下是它的運作方式
如果旗標存在於 `rx->extflags` 中,`split` 會在對主旨字串進行運算之前,從主旨字串的開頭刪除空白。什麼被視為空白取決於主旨是否為 UTF-8 字串,以及是否設定 `RXf_PMf_LOCALE` 旗標。
如果除了此旗標之外還設定了 RXf_WHITE,`split` 會在 Perl 引擎下表現得像 `split " "`。
指示 split 運算子在換行符號 (\n
) 上分割目標字串,而不呼叫正規表示式引擎。
Perl 的引擎會在模式為 /^/
(plen == 1 && *exp == '^'
) 時設定這個,即使在 /^/s
下;請參閱 split。當然,不同的 regex 引擎可能會想要使用不同的語法來使用相同的最佳化。
指示 split 算子在空白處分割目標字串,而不會呼叫 regex 引擎。空白的定義會根據目標字串是否為 UTF-8 字串以及是否設定 RXf_PMf_LOCALE 而有所不同。
Perl 的引擎會在模式為 \s+
時設定這個旗標。
指示 split 算子在字元處分割目標字串。字元的定義會根據目標字串是否為 UTF-8 字串而有所不同。
Perl 的引擎會在模式為空時設定這個旗標,這個最佳化會讓 split //
比原本快很多。它甚至比 unpack
還快。
在 perl 5.18.0 中新增,這個旗標表示正規表示式可能會執行會干擾原位替換的運算。例如,它可能包含後向參照,或是在配對期間指派給非神奇變數(例如 $REGMARK 和 $REGERROR)。當這個旗標被設定時,s///
會略過某些最佳化。
I32 exec(pTHX_ REGEXP * const rx,
char *stringarg, char* strend, char* strbeg,
SSize_t minend, SV* sv,
void* data, U32 flags);
執行正規表示式。參數為
要執行的正規表示式。
這是要與之配對的 SV。請注意,要與之配對的實際字元陣列是由以下所述的參數提供的;SV 僅用於判斷 UTF8ness、pos()
等。
指向字串實際開頭的指標。
指向字串實際結尾後面的字元(即 \0
,如果有)。
指向字串中應開始比對的位置;它可能不等於 strbeg
(例如在 /.../g
的後續反覆運算中)。
字串的最小長度(以位元組為單位,從 stringarg
測量),必須符合;如果引擎到達比對的結尾,但尚未到達字串中的此位置,則應失敗。
最佳化資料;可能會變更。
最佳化旗標;可能會變更。
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
SV* checkstr(pTHX_ REGEXP * const rx);
傳回包含必須出現在樣式中的字串的 SV。split
用於最佳化比對。
void free(pTHX_ REGEXP * const rx);
Perl 在釋放正規表示式樣式時呼叫,以便引擎可以釋放 regexp
結構的 pprivate
成員指向的任何資源。這僅負責釋放私人資料;Perl 會處理釋放 regexp
結構中包含的任何其他內容。
呼叫以取得/設定 $`
、$'
、$&
及其命名等效項 ${^PREMATCH}、${^POSTMATCH} 和 ${^MATCH} 的值,以及編號擷取群組($1
、$2
、...)。
paren
參數對 $1
為 1
,對 $2
為 2
,依此類推,並對特殊變數具有下列符號值
${^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 回呼以提高效率。但是,目前並未在內部繫結命名的擷取變數,而是透過魔法實作。
void numbered_buff_FETCH(pTHX_ REGEXP * const rx, const I32 paren,
SV * const sv);
擷取指定的編號捕獲。sv
應設定為要傳回的標量,標量會作為引數傳遞,而不是從函式傳回,因為當其被呼叫時,Perl 已有一個標量來儲存值,建立另一個標量將是多餘的。標量可以使用 sv_setsv
、sv_setpvn
等函式設定,請參閱 perlapi。
此回呼是 Perl 在污點模式下取消標記其自己的捕獲變數的地方(請參閱 perlsec)。請參閱 regcomp.c 中的 Perl_reg_numbered_buff_fetch
函式,了解如何取消標記捕獲變數(如果您希望您的引擎也執行此操作)。
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 自身的引擎會在任何嘗試修改捕獲變數時發出 croak。要在其他引擎中執行此操作,請使用下列回呼(從 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 並非總是 會在看起來會修改編號捕獲變數的陳述式中發出 croak。這是因為如果 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/;
由於在對 $sv
套用 y///
運算子時 $sv
為 undef
,因此轉寫不會實際執行,程式也不會 die
。這與 5.8 及更早版本的行为不同,因為當時捕獲變數是 READONLY 變數;現在它們在預設引擎中指派時只會 die。
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 回呼,對 %+
和 %-
進行變更,以及在 FIRSTKEY 和 NEXTKEY 的相同情況下呼叫 named_buff_iter
。
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::regname
、re::regnames
或 re::regnames_count
(如果有的話)。前兩個會與 RXapif_ONE
或 RXapif_ALL
結合。
RXapif_REGNAME
RXapif_REGNAMES
RXapif_REGNAMES_COUNT
內部 %+
和 %-
是透過 Tie::Hash::NamedCapture 的真實綁定介面實作。該套件中的方法會呼叫回這些函式。不過,未來版本可能會變更 Tie::Hash::NamedCapture 的使用方式。例如,這可能會透過 magic 實作(需要 mgvtbl 的延伸)。
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);
qr// 魔術物件的祝福套件(如 ref qr//
所見)。建議引擎將其變更為其套件名稱以利辨識,無論是否在物件上實作方法。
此方法傳回的套件也應該在其 @ISA
中包含內部 Regexp
套件。qr//->isa("Regexp")
應始終為 true,無論使用哪個引擎。
範例實作可能是
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);
void* dupe(pTHX_ REGEXP * const rx, CLONE_PARAMS *param);
在執行緒建置中,可能需要複製正規表示法,以便多個執行緒可以使用該樣式。此常式預計會處理 regexp
結構的 pprivate
成員所指的任何私有資料的複製。它會以預先建構的新 regexp
結構作為引數呼叫,pprivate
成員會指向舊的私有結構,而此常式的責任是建構一份副本並傳回其指標(Perl 會使用該指標覆寫傳遞至此常式的欄位)。
這允許引擎複製其私有資料,但必要時也可以修改最終結構。
在非執行緒建置中,此欄位不存在。
這是 Perl 核心私有的,可能會變更。應留空。
REGEXP 結構在 regexp.h 中定義。所有正規表示式引擎都必須能夠在 "comp" 常式中正確建立此結構。
REGEXP 結構包含 Perl 需要了解的所有資料,才能正確使用正規表示式。它包含 Perl 可用來判斷是否真的應使用正規表示式引擎的最佳化資料,以及在各種情況下正確執行模式所需的各種其他控制資訊,例如模式是否以某種方式錨定,或編譯期間使用了哪些旗標,或程式是否包含 Perl 需要了解的特殊建構。
此外,它還包含兩個欄位,供編譯模式的正規表示式引擎私下使用。這些欄位是 intflags
和 pprivate
成員。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 回呼將此欄位設定為旗標參數的值。請參閱 comp 文件以取得有效的旗標。
minlen
minlenret
模式比對所需的最小字串長度(以字元為單位)。這用於透過不費心比對字串末端比允許比對更近的範圍來修剪搜尋空間。例如,如果 minlen 為 10,但字串長度只有 5 個字元,則沒有必要啟動正規表示式引擎。模式無法比對。
minlenret
是在 $& 中找到的字串的最小長度(以字元為單位)。
minlen
和 minlenret
之間的差異可以在以下範例中看到
/ns(?=\d)/
其中 minlen
會是 3,但 minlenret
只會是 2,因為 \d 是必須匹配的,但實際上並未包含在匹配的內容中。此區別特別重要,因為替換邏輯使用 minlenret
來判斷它是否可以進行原地替換(這些替換可能導致速度大幅提升)。
gofs
從 pos() 開始匹配的左偏移量。
substrs
關於最終匹配中必須出現的字串的子字串資料。這目前僅由 Perl 的引擎內部使用,但未來可能會用於所有引擎進行最佳化。
nparens
、lastparen
和 lastcloseparen
這些欄位用於追蹤:範例中有多少個括號擷取群組;哪個是關閉的最高括號(請參閱 "$+" 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
代表 $&
(或 /p
下的 ${^MATCH}
),而 ->offs[paren].end
配對 $$paren
,其中 $paren
= 1>.
precomp
prelen
用於最佳化。precomp
保存已編譯的樣式的副本,而 prelen
則保存其長度。當要編譯新的樣式時(例如在迴圈內),內部 regcomp
算子會檢查最後編譯的 REGEXP
的 precomp
和 prelen
是否等於新的樣式,如果是,則使用舊樣式,而不是編譯新的樣式。
來自 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_PRE
或 REXEC_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 相同的條款下重新散布或修改它。