re
Re
模块
Re
模块摘要
Erlang的类Perl正则表达式。
描述
该模块包含字符串和二进制文件的正则表达式匹配函数。
regular expression
语法和语义类似于Perl 的语法和语义。
该库的匹配算法基于PCRE库,但不是所有的PCRE库都是连接的,并且库的某些部分超出了PCRE提供的范围。目前使用PCRE版本8.40(发布日期2017-01-11)。这里包含了与该模块相关的PCRE文档部分。
注
字符串的Erlang文字语法使用“\”(反斜线)字符作为转义码。你需要在你的代码和shell中用文字字符串转义反斜杠,并加上一个额外的反斜杠,即“\”。
数据类型
mp() = {re_pattern, term(), term(), term(), term()}
包含已编译的正则表达式的不透明数据类型。mp()
保证是一个以原子re_pattern
作为第一个元素的 tuple() ,以便在守卫中进行匹配。未来的Erlang/OTP版本中元组的元素或其他字段的内容可能会发生变化。
nl_spec() = cr | crlf | lf | anycrlf | any
compile_option() =
unicode |
anchored |
caseless |
dollar_endonly |
dotall |
extended |
firstline |
multiline |
no_auto_capture |
dupnames |
ungreedy |
{newline,
nl_spec()
} |
bsr_anycrlf |
bsr_unicode |
no_start_optimize |
ucp |
never_utf
出口
version() -> binary()
此函数的返回是一个字符串,其中包含Erlang/OTP编译中使用的系统的PCRE版本。
compile(Regexp) -> {ok, MP} | {error, ErrSpec}
类型
同compile(Regexp,[])
compile(Regexp, Options) -> {ok, MP} | {error, ErrSpec}
类型
使用下面描述的语法将正则表达式编译为内部格式,稍后将其用作参数to run/2
和run/3
。
如果在程序的生命周期中使用相同的表达式来匹配多个主题,则在匹配之前编译正则表达式非常有用。编译一次并执行多次比每次想要匹配的编译效率高得多。
当unicode
指定选项时,正则表达式将被指定为有效的Unicode charlist()
,否则为任何有效的iodata()
。
备选方案:
unicode
正则表达式被指定为Unicode charlist()
,并且生成的正则表达式代码将针对有效的Unicode charlist()
主题运行。ucp
在使用Unicode字符时还要考虑选项。
anchored
该模式被强制为“锚定”,也就是说,它仅限于匹配搜索字符串中的第一个匹配点(“主题字符串”)。这种效应也可以通过模式本身的适当构造来实现。
caseless
模式中的字母匹配大写和小写字母。它相当于Perl选项/i
,可以通过(?i)
选项设置在模式内进行更改。大写和小写字母在ISO 8859-1字符集中定义。
dollar_endonly
模式中的美元元字符仅在主题字符串的末尾匹配。如果没有这个选项,一美元也会在字符串末尾的换行符之前立即匹配(但不会在任何其他换行符之前)。如果multiline
指定了选项,则忽略此选项。在Perl中没有相应的选项,它不能在模式中设置。
dotall
模式中的一个点匹配所有字符,包括那些指示换行符的字符。如果没有它,当前位置位于换行符时,点不匹配。这个选项相当于Perl选项/s
,它可以通过(?s)
选项设置在模式内进行更改。负面的类,例如[^a]
总是匹配换行符,独立于此选项的设置。
extended
如果设置了此选项,则除了转义或字符类内部以外,模式中的大多数空白字符都会被完全忽略。但是,在(?>引入各种括号内的子模式的序列中不允许使用空格,也不能使用数字量词{1,3}。然而,在项目和后面的量词之间以及在量词和后面的+之间允许可以忽略的空白,表示所有格。
白色空间并未用于包含VT字符(代码11),因为Perl并未将此字符视为空白字符。但是,Perl在版本5.18中进行了更改,因此PCRE随后在版本8.34中,VT现在被视为空白。
这也会导致字符类之外的未转义#与下一个包含换行符的字符之间的字符被忽略。这相当于Perl的/x
选项,它可以通过(?x)
选项设置在模式内进行更改。
使用此选项,可以包含复杂模式中的注释。但是请注意,这仅适用于数据字符。空格字符不能出现在模式中的特殊字符序列中,例如在(?(
引入条件子模式的序列内。
firstline
在主题字符串的第一个换行符之前或之前,需要使用未锚定的模式进行匹配,但匹配的文本可以在换行符上继续。
multiline
默认情况下,PCRE将主题字符串视为由单行字符组成(即使它包含换行符)。“行首”metacharacter(^
)只匹配字符串的起始位置,而“行尾”metacharacter($
)只匹配字符串末尾或终止换行符(除非dollar_endonly
指定了选项)。这与Perl中的相同。
当指定此选项时,“起始行”和“行结束”构造分别与主题字符串中的内部换行符之后或之前匹配,以及最开始和结束时匹配。这相当于Perl选项/m
,可以通过(?m)
选项设置在模式内进行更改。如果有目标字符串没有换行符,或者没有出现的^
或者$
在一个模式,设置multiline
没有任何效果。
no_auto_capture
禁用模式中使用编号的捕获括号。没有遵循的任何开头括号的?
行为就好像跟着一样?:
。命名的圆括号仍然可以用于捕获(并以通常的方式获取数字)。Perl中没有相应的选项。
dupnames
用于识别捕获子模式的名称不必是唯一的。当知道只有命名子模式的一个实例可以匹配时,这可能对某些类型的模式有帮助。下面提供了命名子模式的更多细节。
ungreedy
颠倒量词的“贪婪”,使它们在默认情况下不会贪婪,但如果后面跟着“?”则变得贪婪。它与Perl不兼容。它也可以通过模式中的(?U)
选项设置进行设置。
{newline, NLSpec}
覆盖主题字符串中的换行符的默认定义,即Erlang中的LF(ASCII 10)。
cr
换行符由单个字符cr
(ASCII 13)表示。
lf
换行符由单个字符LF(ASCII 10)表示,默认值为。
crlf
换行符由双字符CRLF(ASCII 13和ASCII 10)序列表示。
anycrlf
前三个序列中的任何一个都将被识别。
any
以上任何一种换行符序列和Unicode序列VT(垂直制表符,U + 000B),FF(换页符,U + 000C),NEL(下一行,U + 0085),LS(行分隔符,U + 2028)和PS(段落分隔符,U + 2029)。
**`bsr_anycrlf`**
具体指定\R仅匹配CR,LF或CRLF序列,而不是特定于Unicode的换行符。
bsr_unicode
具体指定\R将匹配所有Unicode换行符(包括CRLF,等等,默认值)。
no_start_optimize
如果正则表达式中存在“特殊图案开始项目”,则禁用可能发生故障的优化。一个典型的例子是将“DEFABC”与“(* COMMIT)ABC”相匹配,其中PCRE的开始优化将跳过主题直到“A”,并且永远不会意识到(* COMMIT)指令将进行匹配失败。如果您使用“模式开始项目”,则该选项仅与部分讨论相关PCRE Regular Expression Details
。
ucp
指定在解析\B,\b,\D,\d,\S,\s,\W和\w时使用Unicode字符属性。没有这个标志,只使用ISO Latin-1属性。使用Unicode属性会影响性能,但在使用超出ISO Latin-1范围的Unicode字符时语义上是正确的。
never_utf
指定禁止(* UTF)和/或(* UTF8)“模式开始项目”。该标志不能与选项结合使用unicode
。如果要编译来自外部源的ISO拉丁语-1模式,则该模式很有用。
inspect(MP, Item) -> {namelist, binary()}
类型
采用编译的正则表达式和项目,并从正则表达式返回相关数据。唯一受支持的项目是namelist
,返回{namelist, [binary()]}
包含正则表达式中所有(唯一)命名子模式的名称的元组。例如:
1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
{ok,{re_pattern,3,0,0,
<<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
255,255,...>>}}
2> re:inspect(MP,namelist).
{namelist,[<<"A">>,<<"B">>,<<"C">>]}
3> {ok,MPD} = re:compile("(?<C>A)|(?<B>B)|(?<C>C)",[dupnames]).
{ok,{re_pattern,3,0,0,
<<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,
255,255,...>>}}
4> re:inspect(MPD,namelist).
{namelist,[<<"B">>,<<"C">>]}
在第二个例子中注意,重复名称只在返回列表中出现一次,并且列表按字母顺序排列,而不管名称在正则表达式中的位置。如果{capture, all_names}
被指定为选项,名称的顺序与捕获的子表达式的顺序相同run/3
。因此,您可以像这样创建一个名称到值的映射run/3
:
1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
{ok,{re_pattern,3,0,0,
<<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
255,255,...>>}}
2> {namelist, N} = re:inspect(MP,namelist).
{namelist,[<<"A">>,<<"B">>,<<"C">>]}
3> {match,L} = re:run("AA",MP,[{capture,all_names,binary}]).
{match,[<<"A">>,<<>>,<<>>]}
4> NameMap = lists:zip(N,L).
[{<<"A">>,<<"A">>},{<<"B">>,<<>>},{<<"C">>,<<>>}]
replace(Subject, RE, Replacement) -> iodata() | unicode:charlist()
类型
和replace(Subject, RE, Replacement, [])
一样。
replace(Subject, RE, Replacement, Options) ->
iodata() | unicode:charlist()
类型
Subject
用内容替换字符串的匹配部分Replacement
。
run/3
除了该选项capture
不被允许外,允许的选项与for相同。相反{return, ReturnType}
,存在。默认返回类型是以iodata
最小化复制的方式构造的。该iodata
结果可以直接在许多I / O操作中使用。如果需要单位list()
,请指定{return, list}
。如果需要二进制文件,请指定{return, binary}
。
在函数中run/3
,mp()
带有选项的编译unicode
需要Subject
是Unicode charlist()
。如果编译是隐式完成的,并且unicode
为此函数指定了编译选项,则正则表达式将Subject
被指定为有效的Unicode charlist()
。
替换字符串可以包含特殊字符&
,该字符在结果中插入整个匹配表达式,并且将特殊序列\
N(其中N是大于0的整数),\g
N或\g{
N }
,导致子表达式编号N插入到结果。如果正则表达式不生成具有该编号的子表达式,则不插入任何内容。
要在结果中插入&或\,请在前面加上一个。请注意,Erlang已经在文字字符串中给\赋予了一个特殊的含义,所以单个\必须写为"\\"
\,因此是双\ "\\\\"
。
例子:
re:replace("abcd","c","[&]",[{return,list}]).
施予
"ab[c]d"
当
re:replace("abcd","c","[\\&]",[{return,list}]).
施予
"ab[&]d"
与run/3
一样,编译错误会引发badarg
异常。compile/2
可用于获取有关错误的更多信息。
run(Subject, RE) -> {match, Captured} | nomatch
类型
和run(Subject,RE,[])
一样。
run(Subject, RE, Options) ->
{match, Captured} | match | nomatch | {error, ErrType}
类型
参见[`compile / 2`](about:blank#compile_options)。
执行正则表达式匹配,并返回match/{match, Captured}
或nomatch
。正则表达式可以被指定为iodata()
在这种情况下它被自动编译(作为compile/2
)并且被执行,或者被预编译,mp()
在这种情况下它直接对主题执行。
当涉及编译时,badarg
如果发生编译错误,则抛出异常。调用compile/2
以获取有关正则表达式中错误位置的信息。
如果正则表达式是先前编译的,则选项列表只能包含以下选项:
anchored
{capture, ValueSpec}/{capture, ValueSpec, Type}
global
- {match_limit, integer() >= 0}
- {match_limit_recursion, integer() >= 0}
{newline, NLSpec}
notbol
notempty
notempty_atstart
noteol
- {offset, integer() >= 0}
report_errors
否则,所有对功能有效的选项compile/2
也是允许的。选项允许编译和执行匹配,即,anchored
和{newline, NLSpec}
,如果与非预编译的正则表达式一起存在,则影响编译和执行。
如果正则表达式之前用选项编译unicode
,Subject
是一个有效的Unicode来提供charlist()
的,否则任何iodata()
会做。如果涉及编译并且unicode
指定了选项Subject
,则将这两者和正则表达式指定为有效的Unicode charlists()
。
{capture, ValueSpec}/{capture, ValueSpec, Type}
定义成功匹配时从函数返回的内容。该capture
元组可以包含一个值规范,告诉哪些捕获的子字符串将被返回,以及类型规范,告诉如何捕获的子字符串将被返回(作为索引元组,列表或二进制文件)。这些选项在下面详细描述。
如果捕获选项描述没有完成子字符串捕获({capture, none}
),则该函数match
在成功匹配时返回单个原子,否则返回元组{match, ValueList}
。禁用捕获可以通过指定none
或空列表来完成ValueSpec
。
选项report_errors
增加了返回错误元组的可能性。元组或者表示匹配错误(match_limit
或者match_limit_recursion
),或者错误元组具有格式的编译错误{error, {compile, CompileErr}}
。请注意,如果report_errors
未指定选项,则该函数永远不会返回错误元组,但会将编译错误报告为badarg
异常,并且由于超出了匹配限制而导致匹配失败nomatch
。
下列选项与执行有关:
anchored
限制run/3
在第一个匹配位置进行匹配。如果一个模式是通过内容编译的anchored
,或者是凭借其内容来锚定的,那么在匹配的时候就不能使它无法链接,因此没有unanchored
选择。
global
实现全局(重复)搜索(g
Perl中的标志)。每个匹配被返回作为一个单独的list()
如由选项指定包含特定比赛和任何匹配子表达式(或capture
该Captured
返回值的部分是因此具有list()
的list()
秒为单位指定这个选项时。
选项global与匹配空字符串的正则表达式的交互使一些用户感到惊讶。如果global指定了选项,则按照run/3与Perl相同的方式处理空匹配项:任何点的零长度匹配也会重试选项[anchored, notempty_atstart]。如果该搜索给出长度> 0的结果,则包括结果。例:
re:run("cat","(|at)",[global]).
执行下列匹配:
在偏移处
0
正则表达式(|at)
首先匹配字符串的初始位置cat
,给出结果集[{0,0},{0,0}]
(第二个{0,0}
是由于括号表示的子表达式)。由于比赛的长度为0,我们还没有前进到下一个位置。
在偏移处
0
带着
[anchored, notempty_atstart]
搜索将[anchored, notempty_atstart]
在同一位置重试选项,但不会给出长度较长的有趣结果,因此搜索位置会前进到下一个字符(a
)。
在偏移处
1
搜索结果中[{1,0},{1,0}]
,所以这个搜索也是重复的额外选项。
在偏移处
1
带着
[anchored, notempty_atstart]
替代方法ab
已找到,结果为{1,2},{1,2}。结果将被添加到结果列表中,并且搜索字符串中的位置将前进两个步骤。
在偏移处
3
搜索再次匹配空字符串,给[{3,0},{3,0}]
。
在偏移处
1
带着
[anchored, notempty_atstart]
这没有给出长度>0的结果,我们位于最后一个位置,所以全局搜索已经完成。
调用的结果是:
{match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}
notempty
如果指定了此选项,则空字符串不被视为有效匹配。如果存在这种模式的替代品,那么他们就会尝试。如果所有替代方案都与空字符串匹配,则整个匹配失败。
例子:
如果以下模式应用于不以“a”或“b”开头的字符串,它通常会匹配主题开头处的空字符串:
a?b?
使用选项notempty
,此匹配无效,因此可以run/3
进一步搜索字符串以查找“a”或“b”的出现。
notempty_atstart
就像notempty
,除了不允许在主题开始处的空字符串匹配。如果模式被锚定,那么只有当模式包含\ K时才会发生这种匹配。
Perl与notempty
or 没有直接的等价关系notempty_atstart
,但它确实在split()函数内以及使用修饰符时创建了空字符串模式匹配的特例/g
。Perl行为可以在匹配一个空字符串之后模拟,首先在与notempty_atstart
and 相同的偏移处再次尝试匹配anchored
,然后如果失败,则通过推进起始偏移量(见下文)并再次尝试普通匹配。
notbol
指定主题字符串的第一个字符不是一行的开头,所以在它之前不要匹配音调元字符。没有multiline
(在编译时)设置它会导致回音永远不匹配。此选项仅影响旋转元字符的行为。它不影响\A。
noteol
指定主题字符串的结尾不是一行的结尾,所以美元元字符不能与它匹配,也不能(除了在多行模式中)紧接在它之前的换行符。没有multiline
(在编译时)设置它会导致美元永远不匹配。该选项仅影响美元元字符的行为。它不会影响\ Z或\ z。
report_errors
更好地控制错误处理run/3
。指定时,编译错误(如果正则表达式尚未编译)和运行时错误显式返回为错误元组。
以下是可能的运行时错误:
match_limit
PCRE库设置了可以调用内部匹配函数的次数限制。在为Erlang编译的库中默认为10,000,000。如果{error, match_limit}
返回,则正则表达式的执行已达到此限制。这通常被认为是a nomatch
,这是发生这种情况时的默认返回值,但通过指定report_errors
,由于内部呼叫太多而导致匹配失败时通知您。
match_limit_recursion
这个错误非常相似match_limit
,但是当PCRE的内部匹配函数被“递归”调用的次数超过match_limit_recursion
限制时,会出现这个错误,默认值也是10,000,000。请注意,只要值match_limit
和match_limit_default
值保持默认值,match_limit_recursion
错误就不会发生,因为match_limit
错误发生在此之前(每次递归调用也是一次调用,但不是相反)。但是,通过直接在正则表达式字符串中设置限制(请参阅部分PCRE Regular Eexpression Details
)或通过指定选项来更改这两个限制run/3
。
重要的是要理解,当限制匹配时,所谓的“递归”并不是在Erlang机器的C堆栈上或在Erlang进程堆栈上递归。编译到ErlangVM中的PCRE版本使用机器“堆”内存来存储必须在正则表达式匹配中保持递归的值。
{match_limit, integer() >= 0}
以特定于实现的方式限制匹配的执行时间。PCRE文件描述如下:
The match_limit field provides a means of preventing PCRE from using
up a vast amount of resources when running patterns that are not going
to match, but which have a very large number of possibilities in their
search trees. The classic example is a pattern that uses nested
unlimited repeats.
Internally, pcre_exec() uses a function called match(), which it calls
repeatedly (sometimes recursively). The limit set by match_limit is
imposed on the number of times this function is called during a match,
which has the effect of limiting the amount of backtracking that can
take place. For patterns that are not anchored, the count restarts
from zero for each position in the subject string.
这意味着如果使用此选项降低限制,失控的正则表达式匹配可能会更快失败。默认值10,000,000被编译到Erlang VM中。
注
在“长时间运行的BIF”方面,该选项决不会影响Erlang VM的执行。run/3
始终以确保Erlang系统的实时属性的间隔将控制权交给Erlang进程的调度器。
{match_limit_recursion, integer() >= 0}
以特定于实现的方式限制匹配的执行时间和内存消耗,非常类似于match_limit
。PCRE文件描述如下:
The match_limit_recursion field is similar to match_limit, but instead
of limiting the total number of times that match() is called, it
limits the depth of recursion. The recursion depth is a smaller number
than the total number of calls, because not all calls to match() are
recursive. This limit is of use only if it is set smaller than
match_limit.
Limiting the recursion depth limits the amount of machine stack that
can be used, or, when PCRE has been compiled to use memory on the heap
instead of the stack, the amount of heap memory that can be used.
Erlang虚拟机使用PCRE库,在发生正则表达式匹配递归时使用堆内存。这因此限制了机器堆的使用,而不是C堆栈。
指定较低的值可能导致匹配严重递归失败,而它们本应匹配:
1> re:run("aaaaaaaaaaaaaz","(a+)*z").
{match,[{0,14},{0,13}]}
2> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5}]).
nomatch
3> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5},report_errors]).
{error,match_limit_recursion}
这个选项和选项match_limit
只能在极少数情况下使用。建议在篡改这些限制之前了解PCRE库内部。
{offset, integer() >= 0}
在主题字符串中指定的偏移量(位置)处开始匹配。偏移量是从零开始的,所以默认值是{offset,0}
(所有主题字符串)。
{newline, NLSpec}
覆盖主题字符串中的换行符的默认定义,即Erlang中的LF(ASCII 10)。
cr
换行符由单个字符CR(ASCII 13)表示。
lf
换行符由单个字符LF(ASCII 10)表示,默认值为。
crlf
换行符由双字符CRLF(ASCII 13和ASCII 10)序列表示。
anycrlf
前三个序列中的任何一个都被识别。
any
以上任何一种换行符序列和Unicode序列VT(垂直制表符,U + 000B),FF(换页符,U + 000C),NEL(下一行,U + 0085),LS(行分隔符,U + 2028)和PS(段落分隔符,U + 2029)。
**`bsr_anycrlf`**
具体指定\R仅匹配CR LF或CRLF序列,不匹配特定于Unicode的换行符。(重写编译选项。)
bsr_unicode
具体指定\R将匹配所有Unicode换行符(包括CRLF,等等,默认值)。(重写编译选项。)
{capture, ValueSpec}**
/**{capture, ValueSpec, Type}
指定哪些捕获的子字符串以什么格式返回。默认情况下,run/3
捕获子字符串的所有匹配部分和所有捕获子模式(所有模式都会自动捕获)。默认返回类型是字符串捕获部分的(从零开始的)索引,指定为{Offset,Length}
对(index
Type
捕获)。
作为默认行为的一个例子,以下调用作为第一个也是唯一一个捕获的字符串,将主题的匹配部分(中间的“abcd”)作为索引对返回{3,4}
,其中字符位置是基于零的,就像偏移:
re:run("ABCabcdABC","abcd",[]).
此调用的返回值为:
{match,[{3,4}]}
另一个(也是相当常见的)案例是正则表达式匹配所有主题的地方:
re:run("ABCabcdABC",".*abcd.*",[]).
这里的返回值相应地指出了从索引0开始的所有字符串,并且它是10个字符长:
{match,[{0,10}]}
如果正则表达式包含捕获子模式,如:
re:run("ABCabcdABC",".*(abcd).*",[]).
捕获所有匹配的主题以及捕获的子字符串:
{match,[{0,10},{3,4}]}
完整的匹配模式总是给出列表中的第一个返回值,剩余的子模式按照它们在正则表达式中出现的顺序添加。
捕获元组构建如下:
ValueSpec
指定要返回哪些捕获(子)模式。ValueSpec
可以是描述预定义返回值集合的原子,也可以是包含索引或要返回的特定子模式名称的列表。
以下是预定义的子模式集:
all
所有捕获的子模式包括完整的匹配字符串。这是默认设置。
all_names
正则表达式中的
所有命名
子模式,就像list()
指定了按字母顺序排列
的所有名称中的
一个。所有名字的列表也可以通过检索inspect/2
。
first
只有第一个捕获的子模式,它始终是主题的完整匹配部分。所有显式捕获的子模式都被丢弃。
all_but_first
除第一个匹配的子模式外,即所有显式捕获的子模式,但不是主题字符串的完整匹配部分。如果正则表达式作为一个整体与主体的大部分相匹配,但是您感兴趣的部分位于明确捕获的子模式中,则这非常有用。如果返回类型是list
或binary
不返回的子模式,您不感兴趣是一种优化的好方法。
none
返回没有匹配的子模式,match
当匹配成功而不是{match, list()}
返回时,将单个atom 作为函数的返回值。指定一个空列表给出了相同的行为。
值列表是要返回的子模式的索引列表,其中索引0表示所有模式,而1表示正则表达式中的第一个显式捕获子模式,依此类推。在正则表达式中使用命名捕获的子模式(见下文)时,可以使用atom()
s或string()
s来指定要返回的子模式。例如,考虑正则表达式:
".*(abcd).*"
与字符串“ABCabcdABC”匹配,仅捕获“abcd”部分(第一个显式子模式):
re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).
该调用给出以下结果,因为第一个明确捕获的子模式是“(abcd)”,与长度为4的(从零开始的)位置3的主题匹配“abcd”
{match,[{3,4}]}
考虑相同的正则表达式,但是具有明确命名为'FOO'的子模式:
".*(?<FOO>abcd).*"
使用这个表达式,我们仍然可以使用以下调用提供子模式的索引:
re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]).
给出和以前一样的结果。但是,当子模式被命名时,我们也可以在值列表中指定它的名称:
re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]).
这将产生与前面的例子相同的结果,即:
{match,[{3,4}]}
值列表可以指定不存在于正则表达式中的索引或名称,在这种情况下,返回值因类型而异。如果类型为index
,{-1,0}
则返回正则表达式中元组的值而不具有相应的子模式,但对于其他类型(binary
和list
),这些值分别是空的二进制或列表。
Type
可选择指定如何返回捕获的子字符串。如果省略,index
则使用默认值。
Type
可以是下列之一:
index
将捕获的子字符串返回为主题字符串中的字节索引对和主题中匹配字符串的长度(就像主题字符串在匹配时erlang:iolist_to_binary/1
或unicode:characters_to_binary/2
在匹配之前一样)。请注意,选项会unicode
导致(可能是虚拟的)UTF-8编码
二进制文件中面向字节的
索引。因此,字节索引元组{0,2}
在unicode
生效时可以表示一个或两个字符。这看起来可能与直觉相反,但被认为是最有效和最实用的方法。如果需要,返回列表可能会导致更简单的代码。这种返回类型是默认的。
list
返回匹配的子字符串作为字符列表(Erlang string()
的)。它选项unicode
与正则表达式中的\ C序列结合使用,捕获的子模式可以包含无效UTF-8字节(\ C与字节匹配,无论字符编码如何)。在这种情况下,list
捕获可能导致unicode:characters_to_list/2
返回相同类型的元组,即具有标记的三元组,incomplete
或者error
成功转换的字符以及转换的无效UTF-8尾部作为二进制。最好的策略是避免在捕获列表时使用\ C序列。
binary
将匹配的子字符串作为二进制返回。如果使用选项unicode
,这些二进制文件是UTF-8。如果\ C序列一起使用unicode
,二进制文件可能是无效的UTF-8。
在一般情况下,并没有在比赛中分配一个值的子模式返回的元组{-1,0}
的时候type
是index
。未分配的子模式分别作为其他返回类型的空二进制或列表返回。考虑下面的正则表达式:
".*((?<FOO>abdd)|a(..d)).*"
有三个显式捕获子模式,其中左括号位置决定了结果的顺序,因此((?<FOO>abdd)|a(..d))是子模式索引1,(?<FOO>abdd)子模式索引2,(..d)子模式索引3.当与以下字符串匹配时:
"ABCabcdABC"
索引2处的子模式不匹配,因为字符串中不存在“abdd”,但完整模式匹配(由于替代方式a(..d)
)。因此索引2处的子模式未分配,并且默认返回值为:
{match,[{0,10},{3,4},{-1,0},{4,3}]}
设置捕获Type
到binary
给予:
{match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}
这里空的binary(<<>>)表示未分配的子模式。在这种binary情况下,关于匹配的一些信息因此丢失,<<>>也可以是捕获的空字符串。
如果需要区分空匹配和不存在的子模式,请使用type
index
Erlang代码中的最终类型进行转换。
何时选择global
是具体化的,capture
规范分别影响每个匹配,因此:
re:run("cacb","c(a|b)",[global,{capture,[1],list}]).
施予
{match,[["a"],["b"]]}
有关仅影响编译步骤的选项的说明,请参阅compile/2
。
split(Subject, RE) -> SplitList
类型
和split(Subject, RE, [])
一样。
split(Subject, RE, Options) -> SplitList
类型
See [`compile/2`](about:blank#compile_options).
根据提供的正则表达式查找令牌,将输入拆分为部分。分割基本上是通过运行全局正则表达式匹配来完成的,并在发生匹配的地方分割初始字符串。该字符串的匹配部分从输出中删除。
和in一样run/3
,mp()
带有选项的编译unicode
需要Subject
是Unicode charlist()
。如果编译是隐式完成的并且unicode
为此函数指定了编译选项,则正则表达式和Subject
指定为有效的Unicode charlist()
s。
结果以“字符串”列表的形式给出,该字符串是选项return
(默认iodata
)中指定的首选数据类型。
如果在正则表达式中指定了子表达式,那么在结果列表中也会返回匹配的子表达式。例如:
re:split("Erlang","[ln]",[{return,list}]).
施予
["Er","a","g"]
当
re:split("Erlang","([ln])",[{return,list}]).
施予
["Er","l","a","n","g"]
匹配子表达式(由正则表达式中的括号标记)的文本被插入到找到它的结果列表中。这意味着连接整个正则表达式是单个子表达式的分割结果(如最后一个示例中所示)总是会导致原始字符串。
由于在示例中最后一部分没有匹配的子表达式(“g”),所以之后没有插入任何内容。为了使字符串和与子表达式匹配的部分更加明显,可以使用选项group
,该选项将字符串拆分时主题字符串的部分与匹配子表达式的部分组合在一起:
re:split("Erlang","([ln])",[{return,list},group]).
施予
[["Er","l"],["a","n"],["g"]]
这里正则表达式首先匹配“l”,导致“Er”成为结果中的第一部分。当正则表达式匹配时,(唯一)子表达式与“l”绑定,所以“l”与“Er”一起插入到组中。接下来的比赛是“n”,使得“a”成为下一个要返回的部分。由于在这种情况下子表达式绑定到子字符串“n”,因此将“n”插入到该组中。最后一组由剩余的字符串组成,因为找不到更多匹配。
默认情况下,该函数返回字符串的所有部分,包括空字符串,例如:
re:split("Erlang","[lg]",[{return,list}]).
施予
["Er","an",[]]
因为字符串末尾的“g”匹配会留下一个空白的休息符号,这也会返回。此行为不同于Perl中分割函数的默认行为,其中默认删除最后的空字符串。要获得Perl的“修剪”默认行为,请指定trim
为一个选项:
re:split("Erlang","[lg]",[{return,list},trim]).
施予
["Er","an"]
“trim”选项说,“give me as many parts as possible except the empty ones”,这有时可能是有用的。你也可以指定你想要的部分,指定{parts,
N }
:
re:split("Erlang","[lg]",[{return,list},{parts,2}]).
施予
["Er","ang"]
请注意,最后一部分是“ang”,而不是“an”,因为分割被分为两部分,并且在给出足够部分时分裂停止,这就是为什么结果不同于trim
。
在这个inData中,不可能有三个以上的部分,所以
re:split("Erlang","[lg]",[{return,list},{parts,4}]).
给出与默认值相同的结果,将其视为“an infinite number of parts”。
指定0
为零件的数量与选项具有相同的效果trim
。如果子表达式被捕获,则在结束时匹配的空子表达式也将被从结果中剥离,如果trim
或者{parts,0}
被指定的话。
trim
行为完全对应于Perl默认值。{parts,N}
,其中N是正整数,与具有正数值第三参数的Perl行为完全对应。split/3
当一个负整数被指定为Perl例程的第三个参数时,默认行为对应于Perl行为。
以前未说明的功能选项摘要run/3
*
{return,ReturnType}
指定原始字符串的部分在结果列表中的显示方式。有效的类型:
iodata
这种变体iodata()
使得数据与当前实现(通常是二进制,但不依赖于它)的复制最少。
binary
所有部分都以二进制形式返回。
list
作为字符列表返回的所有部分(“字符串”)。
**`group`**
将字符串的部分与匹配正则表达式的子表达式的字符串的部分组合在一起。
从函数的返回值是在这种情况下list()
的list()
秒。每个子列表以从主题字符串中挑选出的字符串开始,然后按照正则表达式中出现的顺序匹配每个子表达式。
{parts,N}
指定要将主题字符串拆分为的部分的数量。
对于特定的最大零件infinity
数量以及可能的最大零件数量(缺省),零件的数量应为正整数。指定{parts,0}
尽可能多的部分尽可能地忽略最后的空白部分,与指定相同trim
。
trim
指定结果列表末尾的空白部分将被忽略。与指定相同{parts,0}
。这对应split
于Perl中内置函数的默认行为。
类Perl正则表达式语法
以下部分包含本模块使用的正则表达式的参考资料。该信息基于PCRE文档,其中该模块的行为与PCRE库的行为不同。
PCRE正则表达式详细信息
以下各节详细介绍PCRE支持的正则表达式的语法和语义。Perl的正则表达式在它自己的文档中有描述,一般的正则表达式在很多书中都有介绍,其中一些有很多例子。Jeffrey Friedl的O'Reilly出版的“掌握正则表达式”涵盖了非常详细的正则表达式。PCRE正则表达式的这种描述是作为参考材料的。
参考资料分为以下几部分:
Special Start-of-Pattern Items
Characters and Metacharacters
Backslash
Circumflex and Dollar
Full Stop (Period, Dot) and \N
Matching a Single Data Unit
Square Brackets and Character Classes
Posix Character Classes
Vertical Bar
Internal Option Setting
Subpatterns
Duplicate Subpattern Numbers
Named Subpatterns
Repetition
Atomic Grouping and Possessive Quantifiers
Back References
Assertions
Conditional Subpatterns
Comments
Recursive Patterns
Subpatterns as Subroutines
Oniguruma Subroutine Syntax
Backtracking Control
特殊模式开始项目
一些可以传递给的选项compile/2
也可以在模式开始时由特殊项目设置。这些不是Perl兼容的,但提供这些选项是为了让模式编写人员无法更改处理模式的程序而访问这些选项。任何数量的这些项目都可以出现,但它们必须全部在模式字符串的开始处在一起,并且字母必须是大写字母。
UTF支撑
Unicode支持基本上是基于UTF-8的。要使用Unicode字符,您可以调用compile/2
或run/3
使用选项unicode
,或者模式必须以以下特殊序列之一开头:
(*UTF8)
(*UTF)
两个选项都具有相同的效果,输入字符串被解释为UTF-8。请注意,根据这些说明,列表自动转换为UTF-8不是由re
函数执行的。因此,不推荐使用这些序列。改为unicode
运行时添加选项compile/2
。
一些允许其用户提供模式的应用程序出于安全原因可能希望将其限制为非UTF数据。如果never_utf
在编译时设置选项,则不允许(* UTF)等,并且它们的外观会导致错误。
Unicode属性支持
下面是另一个特殊的序列,可以出现在模式的开头:
(*UCP)
这与设置选项具有相同的效果ucp:它使\ d和\ w这样的序列使用Unicode属性来确定字符类型,而不是仅通过查找表识别代码<256的字符。
禁用启动优化
如果一个模式开始(*NO_START_OPT)
,它与no_start_optimize
编译时的设置选项具有相同的效果。
纽兰公约
PCRE支持五种用于指示字符串换行符的约定:单个CR(回车)字符,单个LF(换行符)字符,两个字符的序列CRLF,前面三个中的任何一个,以及任何Unicode换行符序列。
还可以通过使用以下五个序列之一启动模式字符串来指定换行符约定:
(* CR)回车符(* LF)换行符(* CRLF) >回车符后跟换行符(* ANYCRLF)以上三者中的任何一个(* ANY)所有Unicode换行符序列
这些覆盖默认值和指定的选项compile/2
。例如,以下模式将约定更改为CR:
(*CR)a.b
这种模式匹配a\nb
,因为LF不再是换行符。如果存在多于一个,则使用最后一个。
换行符约定会影响旋转和美元断言的真实位置。它还会影响dotall
未设置时的点元字符的解释以及\N的行为。但是,它不影响\R转义序列匹配的内容。默认情况下,这是用于Perl兼容性的任何Unicode换行符序列。但是,这可以改变;请参阅部分中\R的说明Newline Sequences
。\R设置的更改可以与新行约定的更改结合使用。
设置匹配和递归限制
调用者run/3
可以对调用内部match()函数的次数和递归调用的最大深度设置限制。提供这些设施是为了捕捉由具有巨大匹配树的模式引起的失控匹配(典型的例子是具有嵌套无限重复的模式)并避免由于递归太多而耗尽系统堆栈。当达到其中一个限制时,pcre_exec()
返回错误。限制也可以通过以下形式的模式开始处的项目来设置:
(*LIMIT_MATCH=d)
(*LIMIT_RECURSION=d)
这里d是任意数字的小数位数。但是,该设置的值必须小于调用者设置的值run/3
才能起作用。也就是说,模式编写器可以降低程序员设置的限制,但不会提高它。如果这些限制之一有多个设置,则使用较低的值。
在Erlang虚拟机中,这两个限制的默认值都是10,000,000。请注意,递归限制不会影响虚拟机的堆栈深度,因为Erlang的PCRE以这样的方式编译,即匹配函数从不在C堆栈上递归。
请注意,LIMIT_MATCH
并LIMIT_RECURSION
只能减少由主叫方设置的限制值,不会增加他们。
字符和元字符
正则表达式是从左到右与主题字符串匹配的模式。大多数角色代表自己的模式,并与主题中的相应角色相匹配。作为一个简单的例子,下面的模式匹配与自身相同的主题字符串的一部分:
The quick brown fox
当指定了caseless
大小写匹配(选项)时,字母与大小写无关。
正则表达式的力量来自于在模式中包含替代和重复的能力。这些都是使用元字符
编码的模式,它们并不代表它们自己,而是以某种特殊的方式进行解释。
存在两组元字符:那些在方括号内除模式内的任何地方识别的元字符,以及在方括号内识别的元字符。在方括号之外,元字符如下所示:
**具有多种用途的常规转义字符
^ 断言字符串开头(或多行模式下的行)
$ 断言字符串结尾(或行,多行模式)
。匹配除换行符之外的任何字符(默认情况下)
[ 开始字符类定义
| 替代分支的开始
(开始子模式
)结束子模式
?扩展(也是0或1量词,还有量词最小化器
* 0或更多量词
+ 1或更多量词,也是“所有格量词”)的含义
{**开始最小/最大量词
方括号内的部分模式称为“字符类”。以下是字符类中唯一的元字符:
**一般转义字符
^ 否定类,但只限于第一个字符
- 表示字符范围第六个字符类(仅当后面跟有Posix语法时)
**终止字符类
下面的部分描述了每个元字符的使用。
反斜杠
反斜杠字符有很多用途。首先,如果后面跟着一个不是数字或字母的字符,它会带走角色可以拥有的任何特殊含义。将反斜杠用作转义字符既适用于内部字符类,也适用于外部字符类。
例如,如果你想匹配*字符,你可以在模式中编写\ *。如果以下字符将被解释为元字符,则此转义操作适用,因此在带有反斜杠的非字母数字前面指定它代表自己始终是安全的。特别是,如果你想匹配一个反斜杠,write\。
在unicode
模式下,只有ASCII数字和字母在反斜杠后有特殊含义。所有其他字符(特别是代码点大于127的字符)都被视为文字。
如果使用option编译模式extended
,则会忽略模式中的空格(字符类中除外)以及字符类和下一个换行符之外的字符之间的字符。可以使用转义反斜杠来包含空格或#字符作为模式的一部分。
要从一系列字符中删除特殊含义,请将它们放在\ Q和\ E之间。这与Perl的不同之处在于,$和@在PCRE中作为\ Q ... \ E序列中的文字处理,而$和@在Perl中引起可变插值。注意以下例子:
Pattern PCRE matches Perl matches
\Qabc$xyz\E abc$xyz abc followed by the contents of $xyz
\Qabc\$xyz\E abc\$xyz abc\$xyz
\Qabc\E\$\Qxyz\E abc$xyz abc$xyz
\ Q ... \ E序列在字符类内部和外部均被识别。\ Q之前未被隔离的\ E被忽略。如果\ Q在模式后面没有跟随\ E,字面解释会继续到模式的末尾(也就是\ E在末尾)。如果孤立的\ Q在一个字符类中,这会导致错误,因为字符类没有终止。
非印刷字符
反斜杠的第二次使用提供了以可见方式编码图案中的非打印字符的方式。对于非打印字符的外观没有限制,除了终止模式的二进制零之外。当通过文本编辑准备模式时,使用以下转义序列之一比它表示的二进制字符更容易:
\ a
报警,即BEL字符(十六进制07)\ cx
“Control-x”,其中x是任何ASCII字符\ e
Escape(十六进制1B)\ f
换页符(十六进制0C)\ n
换行符(十六进制0A )\ r
回车符(十六进制0D)\ t
制表符(十六进制09)\ 0dd
具有八进制代码的字符0dd \ ddd
具有八进制代码ddd的字符或具有八进制代码ddd的反向引用\ o {ddd ..}
字符.. \ xhh
带十六进制代码的字符hh \ x {hhh ..}
带有十六进制代码hhh的字符..
注
请注意,\ 0dd始终是八进制代码,而\ 8和\ 9是文字字符“8”和“9”。
\ cx对ASCII字符的精确影响如下所示:如果x是小写字母,它将转换为大写字母。然后字符的位6(十六进制40)被反转。因此\ cA到\ cZ变成十六进制01到十六进制1A(A是41,Z是5A),但是\ c {变成十六进制3B({是7B)和\ c; 变成十六进制7B(;是3B)。如果\ c后面的数据项(字节或16位值)的值大于127,则会发生编译时错误。这会锁定所有模式下的非ASCII字符。
c工具是为ASCII字符而设计的,但是扩展到Unicode之后,它就比以前更没用了。
在\ 0之后,最多读取两个八进制数字。如果少于两位数字,则只使用那些存在的数字。因此,序列\ 0 \ x \ 015指定了两个二进制零后跟一个CR字符(代码值13)。如果后面的模式字符本身是一个八进制数字,请确保在初始零后提供两位数字。
转义符\ o后面必须紧跟一系列的八进制数字,用大括号括起来。如果不是这种情况,则会发生错误。这个转义是Perl最近的补充; 它提供了将字符代码点指定为大于0777的八进制数字的方法,它还允许明确指定八进制数和后向引用。
为了更清晰明确,最好避免跟随\大于零的数字。请使用\ o {}或\ x {}指定字符编号,\ g {}指定反向引用。以下段落描述了旧的,模棱两可的语法。
处理一个反斜杠后跟一个0以外的数字很复杂,并且Perl在最近的版本中已经改变,导致PCRE也改变。在字符类外,PCRE将该数字和任何后续数字读取为十进制数字。如果数字<8,或者表达式中至少有许多先前捕获了左括号,则将整个序列作为反参考。稍后在讨论带圆括号的子模式之后提供了如何工作的描述。
在一个字符类中,或者如果\之后的十进制数大于7并且没有那么多捕获子模式,PCRE将字符字符“8”和“9”处理为\ 8和\ 9,否则重新读取到反斜杠后面的三个八进制数字,并使用它们生成数据字符。任何后续数字都代表它们自己。例如:
\ 040编写ASCII空间的另一种方式\ 40同样,只要有<40个以前的捕获子模式\ 7总是一个后退引用\ 11可以是后退引用或另一种写入制表符的方式\ 011总是一个制表符\ 0113后面带有字符“3”的选项卡\ 113可以是反向参考,否则带八进制代码的字符为113 \ 377可以是反向参考,否则为值255(十进制)\ 81可以是反向参考或两个字符“8 “和”1“
请注意,使用此语法指定的八进制值> = 100不能由前导零引入,因为不会有超过三个八进制数字被读取。
默认情况下,在\ x之后没有跟随{,从零到两个十六进制数字被读取(字母可以是大写或小写)。\ x {和}之间可能会出现任意数量的十六进制数字。如果\ x {和}之间出现十六进制数字以外的字符,或者如果没有终止},则会发生错误。
值小于256的字符可以由\ x的两种语法中的任何一种来定义。他们处理的方式没有区别。例如,\ xdc与\ x {dc}完全相同。
字符值约束
使用八进制或十六进制数字指定的字符仅限于某些值,如下所示:
8位非UTF模式
<0x100
8位UTF-8模式
<0x10ffff和有效的编码点
无效的Unicode代码点范围是0xd800到0xdfff(即所谓的“代理”代码点)和0xffef。
字符类中的转义序列
定义单个字符值的所有序列都可以在字符类内部和外部使用。此外,在字符类中,\b被解释为后退字符%28十六进制08%29。
字符类中不允许使用n。B、\R和\X在字符类中并不特殊。与其他未识别的转义序列一样,它们被视为字面字符“B”、“R”和“X”。在字符类之外,这些序列具有不同的含义。
不支持逃逸序列
在Perl中,序列\l、\L、\u和\u由其字符串处理程序识别,用于修改以下字符的情况。PCRE不支持这些转义序列。
绝对和相对反向引用
序列\g后面跟着一个无符号或负数,可选地括在大括号中,是绝对或相对的反向引用。可以将命名的回退引用编码为\g{name}。后面的引用将在后面讨论括号大小的子模式之后进行讨论。
绝对和相对子程序调用
为了与Oniguruma兼容,非Perl语法\ g后跟一个用尖括号或单引号括起来的名称或数字,是将子模式引用为“子例程”的替代语法。细节将在稍后讨论。请注意,\ g {...}(Perl语法)和\ g <...>(Oniguruma语法)不是同义词。前者是后向参照,后者是子程序调用。
属字符类型
反斜杠的另一种用法是指定泛型字符类型:
\ d
任何十进制数字\ D
任何非十进制数字的字符\ h
任何水平空白字符\ H
任何非水平空白字符的字符\ s
任何空格字符\ S
任何非空白字符的字符\ v
任何垂直空白字符\ V
任何不是垂直空白字符的字符\ w
任何“字”字符\ W
任何“非字”字符
还有单个序列\N,它与非换行符匹配。这与“.”是一样的。元字符dotall
未设置时。Perl也使用\N来按名称匹配字符,但PCRE不支持这一点。
每对小写和大写转义序列将整个字符集分割成两个不相交的集合。任何给定的字符都与每对中的一个匹配,并且只匹配一个。序列可以出现在字符类内部和外部。它们各自匹配适当类型的一个字符。如果当前匹配点位于主题字符串的末尾,则全部失败,因为没有匹配的字符。
为了与Perl兼容,\s没有用来匹配VT字符(代码11),这使得它与POSIX“空间”类不同。但是,Perl在版本5.18中添加了VT,而PCRE在8.34版中也是如此。现在默认的\ s字符是HT(9),LF(10),VT(11),FF(12),CR(13)和空格(32),它们在“C”语言环境中定义为空白。如果发生特定于语言环境的匹配,此列表可能会有所不同。例如,在某些语言环境中,“不分隔空格”字符(\xA0)被识别为空格,而在另一些语言中,VT字符不识别。
“word”字符是下划线或任何字母或数字。默认情况下,字母和数字的定义由PCRE低值字符表控制,在Erlang的情况下(无选项unicode
)是ISO Latin-1字符集。
默认情况下,在unicode
模式下,值大于255的字符,即ISO Latin-1字符集外的所有字符都不匹配\d,\s或\w,并且始终匹配\D,\S和\W 。这些序列在UTF支持可用之前保留其原有含义,主要是出于效率原因。但是,如果ucp
设置了选项,则会更改该行为,以便使用Unicode属性确定字符类型,如下所示:
\d
\p {Nd}匹配的
任何字符(十进制数字)\s
\p {Z}或\h或\v \w的
任何字符匹配\p {L}或\p {N}加上下划线
大写转义符与反转字符集匹配。请注意,\d仅匹配十进制数字,而\w匹配任何Unicode数字,任何Unicode字母和下划线。还要注意,ucp
影响\b和\B,因为它们是以\w和\W来定义的。匹配这些序列在ucp
设置时明显较慢。
序列\h,\H,\v和\V是在版本5.10中添加到Perl中的功能。与其他序列(默认情况下仅匹配ASCII字符)相比,这些序列总是与特定的高值代码点相匹配,无论是否ucp
设置。
以下是水平空格字符:
U + 009
水平制表符U + 0020
空间U + 00A0不间断
空间U + 1680
Ogham空格标记U + 180E
蒙古语元音分隔符U + 2000
En四U + 2001
Em四U + 2002
En空间U + 2003
Em空间U + 2004
三次元空间U + 2005
四次元空间U + 2006
六次元空间U + 2007
图形空间U + 2008
标点符号空间U + 2009
薄空间U + 200A
发空间U + 202F
窄不间断
空间U + 205F
中等数学空间U + 3000
表意空间
以下是垂直空格字符:
U + 000A
换行符(LF)U + 000B
垂直制表符(VT)U + 000C
换页符(FF)U + 000D
回车符(CR)U + 0085
下一行(NEL)U + 2028
行分隔符U + 2029
段落分隔符
在8位非UTF-8模式下,只有代码点<256的字符才是相关的。
Newline序列
在字符类外部,默认情况下,转义序列\R匹配任何Unicode换行符序列。在非UTF-8模式下,\R等同于以下内容:
(?>\r\n|\n|\x0b|\f|\r|\x85)
这是“atomic group”的一个例子,详情如下。
这个特定的组匹配两个字符的序列CR,其后跟LF或者单个字符LF(换行,U+000A),VT(垂直制表符,U+000B),FF(换页,U+000C) ,CR(回车,U+000D)或NEL(下一行,U+0085)。双字符序列被视为不能拆分的单个单元。
在Unicode模式下,添加两个以上字符,其代码点大于255:LS(行分隔符,U+2028)和PS(段落分隔符U+2029)。这些字符被识别时不需要Unicode字符属性支持。
bsr_anycrlf
通过在编译时或模式匹配时设置选项,可以将R限制为仅匹配CR,LF或CRLF(而不是完整的Unicode行结尾集)。(BSR是“反斜杠R”的缩写)。当PCRE构建时,这可以作为默认值; 如果是这样,可以通过选项请求其他行为bsr_unicode
。这些设置也可以通过以下列序列之一开始模式字符串来指定:
(* BSR_ANYCRLF)仅限
CR,LF或CRLF (* BSR_UNICODE)
任何Unicode换行符序列
它们会覆盖指定给编译函数的缺省值和选项,但它们本身可以被指定给匹配函数的选项覆盖。请注意,这些与Perl不兼容的特殊设置只能在模式开始时识别,并且必须使用大写。如果存在多于一个,则使用最后一个。它们可以与换行符的改变结合使用; 例如,模式可以从以下开始:
(*ANY)(*BSR_ANYCRLF)
它们也可以与(* UTF8),(* UTF)或(* UCP)特殊序列组合。在字符类中,\R被视为无法识别的转义序列,因此默认情况下匹配字母“R”。
Unicode字符属性
可以使用另外三个匹配具有特定属性的字符的转义序列。在8位非UTF-8模式下,这些序列仅限于测试代码点<256的字符,但它们在此模式下工作。以下是额外的转义序列:
\p {xx}
属性为xx \P {xx}
的字符不带属性的字符xx \X
Unicode扩展字形群集
上面xx
表示的属性名称仅限于Unicode脚本名称,一般类别属性“Any”,它匹配任何字符(包括换行符)以及一些特殊的PCRE属性(将在下一节中介绍)。其他Perl属性(如“InMusicalSymbols”)目前不受PCRE支持。请注意,\P {Any}不匹配任何字符,并始终导致匹配失败。
Unicode字符集被定义为属于某些脚本。来自这些集合之一的字符可以使用脚本名称进行匹配,例如:
\p{Greek} \P{Han}
那些不属于已识别脚本的部分被归类为“Common”。以下是脚本的当前列表:
- Arabic
- Armenian
- Avestan
- Balinese
- Bamum
- Bassa_Vah
- Batak
- Bengali
- Bopomofo
- Braille
- Buginese
- Buhid
- Canadian_Aboriginal
- Carian
- Caucasian_Albanian
- Chakma
- Cham
- Cherokee
- Common
- Coptic
- Cuneiform
- Cypriot
- Cyrillic
- Deseret
- Devanagari
- Duployan
- Egyptian_Hieroglyphs
- Elbasan
- Ethiopic
- Georgian
- Glagolitic
- Gothic
- Grantha
- Greek
- Gujarati
- Gurmukhi
- Han
- Hangul
- Hanunoo
- Hebrew
- Hiragana
- Imperial_Aramaic
- Inherited
- Inscriptional_Pahlavi
- Inscriptional_Parthian
- Javanese
- Kaithi
- Kannada
- Katakana
- Kayah_Li
- Kharoshthi
- Khmer
- Khojki
- Khudawadi
- Lao
- Latin
- Lepcha
- Limbu
- Linear_A
- Linear_B
- Lisu
- Lycian
- Lydian
- Mahajani
- Malayalam
- Mandaic
- Manichaean
- Meetei_Mayek
- Mende_Kikakui
- Mende_Kikakui
- Meroitic_Hieroglyphs
- Miao
- Modi
- Mongolian
- Mro
- Myanmar
- Nabataean
- New_Tai_Lue
- Nko
- Ogham
- Ol_Chiki
- Old_Italic
- Old_North_Arabian
- Old_Permic
- Old_Persian
- Oriya
- Old_South_Arabian
- Old_Turkic
- Osmanya
- Pahawh_Hmong
- Palmyrene
- Pau_Cin_Hau
- Phags_Pa
- Phoenician
- Psalter_Pahlavi
- Rejang
- Runic
- Samaritan
- Saurashtra
- Sharada
- Shavian
- Siddham
- Sinhala
- Sora_Sompeng
- Sundanese
- Syloti_Nagri
- Syriac
- Tagalog
- Tagbanwa
- Tai_Le
- Tai_Tham
- Tai_Viet
- Takri
- Tamil
- Telugu
- Thaana
- Thai
- Tibetan
- Tifinagh
- Tirhuta
- Ugaritic
- Vai
- Warang_Citi
- Yi
每个字符只有一个Unicode常规类别属性,由两个字母的首字母缩写词指定。为了与Perl兼容,可以通过在左大括号和属性名称之间加入一个回音来指定否定。例如,\p {^ Lu}与\P{Lu}相同。
如果\p或\P只指定了一个字母,则它包含以该字母开头的所有常规类别属性。在这种情况下,如果没有否定,转义序列中的大括号是可选的。以下两个例子具有相同的效果:
\p{L}
\pL
支持以下通用类属性代码:
C
OtherCc
Co
ntrolCf
FormatCn
UnassignedCo
P
rivate useCs
S
urrogateL
L
etterLl
Lo
wercase letterLm
M
odifier letterLo
Other letterLt
Title case letterLu
Uppercase letterM
M
arkMc
S
pacing markMe
Enclosing markMn
No
n-spacing markN
N
umberNd
Decimal numberNl
L
etter numberNo
Other numberP
P
unctuationPc
Co
nnector punctuationPd
Dash punctuationPe
C
lose punctuationPf
Final punctuationPi
Initial punctuationPo
Other punctuationPs
Open punctuationS
S
ymbolSc
C
urrency symbolSk
M
odifier symbolSm
M
athematical symbolSo
Other symbolZ
S
eparatorZl
L
ine separatorZp
P
aragraph separatorZs
S
pace separator
L&的特殊属性也受到支持。它匹配具有Lu,Ll或Lt属性的字符,即未被分类为修饰符或“其他”的字母。
Cs(代理)属性仅适用于U+D800到U+DFFF范围内的字符。这些字符在Unicode字符串中无效,因此无法通过PCRE进行测试。Perl不支持Cs属性。
由Perl支持的属性名称的长同义词(例如\p{Letter})不受PCRE支持。不允许在“是”的前面添加任何这些属性的前缀。
Unicode表中没有字符具有Cn(未分配)属性。该属性被假定为不在Unicode表中的任何代码点。
指定无外壳匹配不会影响这些转义序列。例如,\p{Lu}总是只匹配大写字母。这与当前版本的Perl的行为不同。
由Unicode属性匹配字符并不快,因为PCRE必须执行多级表查找来查找字符属性。这就是为什么像\d和\w这样的传统转义序列默认情况下不使用PCRE中的Unicode属性的原因。但是,您可以通过设置选项ucp
或通过(* UCP)启动模式来完成此操作。
扩展的字形集群
\X转义匹配形成“扩展字形群集”的任意数量的Unicode字符,并将该序列视为原子组(见下文)。直到并包括版本8.31,PCRE匹配了更早的,更简单的定义,相当于(?>\PM\pM*)。也就是说,它匹配了一个没有“mark”属性的字符,后跟零个或多个带有“mark”属性的字符。带有“mark”属性的字符通常是影响前一个字符的非间距重音。
这个简单的定义在Unicode中被扩展为包含更复杂的复合字符,方法是给每个字符一个字形破坏属性,并创建使用这些属性定义扩展字形集群边界的规则。在晚于8.31的PCRE版本中,\X匹配这些集群中的一个。
\X总是匹配至少一个字符。然后根据以下规则决定是否添加更多字符来结束集群:
- 在主题字符串的末尾结束。
- 不要在CR和LF之间结束;否则在任何控制字符后结束。
- 不要打破Hangul(韩文)音节序列。韩文字符有五种类型:L,V,T,LV和LVT。一个L字符可以后跟一个L,V,LV或LVT字符。一个LV或V字符可以跟一个V或T字符。一个LVT或T字符只能跟一个T字符。
- 在扩展字符或间距标记之前不要结束。带有“extend”属性的字符总是具有“extend”字形断开属性。
- 不要在前面的字符之后结束。
- 否则,结束群集。
PCRE附加性能
除了前面描述的标准Unicode属性之外,PCRE还支持另外四种可以将传统转义序列(如\w和\s)转换为使用Unicode属性的可能性。当ucp
选项通过时,PCRE在内部使用这些非标准的非Perl属性。但是,它们也可以明确使用。属性如下:
Xan
任何字母数字字符。匹配具有L(字母)或N(数字)属性的字符。
XPS
任何Posix空间字符。匹配字符选项卡,换行符,垂直制表符,换页符,回车符和具有Z(分隔符)属性的任何其他字符。
XSP
任何Perl空间字符。与Xps相同,但不包括垂直制表符。
XWD
任何Perl“Word”字符。匹配与Xan相同的字符,加上下划线。
Perl和POSIX空间现在是相同的。Perl在版本5.18中将VT添加到了它的空间字符集中,而PCRE在8.34版中进行了更改。
Xan匹配具有L(字母)或N(数字)属性的字符。Xps匹配字符选项卡,换行符,垂直制表符,换页符或回车符以及具有Z(分隔符)属性的任何其他字符。Xsp与Xps相同; 它用于排除垂直选项卡,以实现Perl兼容性,但Perl已更改,因此在版本8.34中遵循PCRE。Xwd匹配与Xan相同的字符,并加上下划线。
还有另一个非标准属性Xuc,它匹配任何可以用C ++和其他编程语言中的通用字符名称表示的字符。除了代理U + D800到U + DFFF外,它们是字符$,@,`(重音符号)和所有带有Unicode代码点> = U + 00A0的字符。注意大多数基本(ASCII)字符被排除。(通用字符名称的形式是\uHHHH或\UHHHHHHHH,其中H是一个十六进制数字。请注意,Xuc属性与这些序列不匹配,但它们表示的字符不匹配。)
重置匹配启动
转义序列\ K导致任何先前匹配的字符不包含在最终的匹配序列中。例如,以下模式匹配“foobar”,但报告它已匹配“bar”:
foo\Kbar
该功能类似于后向断言(如下所述)。但是,在这种情况下,真正匹配之前的主体部分不必具有固定长度,因为后向断言具有固定长度。使用\ K不会干扰捕获的子串的设置。例如,当以下模式匹配“foobar”时,第一个子字符串仍然设置为“foo”:
(foo)\Kbar
Perl文档指出,在断言中使用\K是“没有明确定义”。在PCRE中,当肯定断言发生时,\K被采取行动,但在否定断言中被忽略。请注意,如果(?= ab \K)等模式匹配,则报告的比赛开始时间可能会大于比赛结束时间。
简单断言
反斜杠的最终用途是用于某些简单的断言。断言指定了匹配中特定点必须满足的条件,而不消耗主题字符串中的任何字符。下面描述使用子模式进行更复杂的断言。以下是相反的断言:
\b
匹配单词边界。\B
当不在单词边界时匹配。\A
匹配在主题的开始。\Z
匹配主题的末尾,并在主题末尾的换行符之前匹配。\z
仅在主题末尾匹配。\G
匹配主题中的第一个匹配位置。
在字符类中,\b具有不同的含义;它匹配退格字符。如果其他任何断言出现在字符类中,默认情况下它会匹配相应的文字字符(例如\ B匹配字母B)。
单词边界是主题字符串中当前字符和前一个字符不匹配\w或\W(即一个匹配\w,另一个匹配\W)的位置,或者该字符的开头或结尾如果第一个或最后一个字符分别与\w匹配,则为字符串。在UTF模式下,可以通过设置选项来更改\w和\W的含义ucp
。完成后,它也会影响\b和\B。PCRE和Perl没有单独的“单词开始”或“单词结束”metasequence。然而,无论如何\b通常确定它是哪一个。例如,片段\ba在单词的开头匹配“a”。
\A,\Z和\z断言与传统的曲调和美元(在下一节中描述)不同,它们只在主题字符串的开头和结尾匹配,无论设置了什么选项。因此,它们独立于多线模式。这三个断言不受选项的影响,notbol
或noteol
仅影响旋转元和美元元字符的行为。但是,如果参数startoffset
的run/3
不为零,表明匹配是比主体的开始以外的其他点开始,\A不能比拟的。\Z和\z之间的区别在于,\Z匹配字符串末尾的换行符之前,最后匹配换行符,而\z只匹配末尾。
只有当当前匹配位置在匹配的起始点时,\G断言才为真,如参数startoffset
的run/3
。它与\A的不同之处在于其值startoffset
不为零。通过run/3
用适当的参数多次调用,你可以模仿Perl选项/g
,并且在这种实现中,\ G可以是有用的。
然而,请注意,\G作为当前匹配的开始的PCRE解释与Perl相比有微妙差异,Perl将其定义为前一次匹配的结束。在Perl中,当以前匹配的字符串为空时,这些可能会有所不同。由于PCRE一次只能匹配一个,所以无法重现此行为。
如果模式的所有选项都以\G开头,则表达式将锚定到起始匹配位置,并在编译的正则表达式中设置“anchored”标志。
Circumflex和美元
Circumflex和美元元字符是零宽度断言。也就是说,他们测试一个特定的条件为真,而不消耗主题字符串中的任何字符。
在字符类外部,在缺省匹配模式下,只有在当前匹配点位于主题字符串的起始位置时,circumflex字符才为真。如果争论startoffset
的run/3
是非零,如果选项抑扬,则不能使用multiline
未设置。在角色类中,回音有一个完全不同的含义(见下文)。
如果涉及一些替代方案,则Circumflex不需要成为模式的第一个字符,但是如果模式匹配该分支,它将成为每个替代方案中的第一个选项。如果所有可能的选择都以旋律开始,也就是说,如果该模式仅限于在主体开始时匹配,则被称为“锚定”模式。(还有其他构造可以使模式被锚定。)
美元字符是一个断言,只有在当前匹配点位于主题字符串的结尾处,或紧接在字符串末尾的换行符之前(默认情况下)才为真。但请注意,它与换行符不匹配。如果涉及到一些替代方案,美元不必是模式的最后一个字符,但它应该是任何分支中的最后一个分支。美元在角色等级中没有特殊含义。
通过dollar_endonly
在编译时设置选项,可以更改美元的含义,以便它仅在字符串的最后匹配。这不会影响\Z断言。
如果multiline
设置了选项,则会更改音符和美元字符的含义。当这种情况发生时,旋转曲线在内部换行符后面和主题字符串开始处立即匹配。它在结束字符串的换行符后不匹配。一美元在字符串中的任何换行符之前匹配,并且在最后multiline
设置时匹配。当将换行符指定为两个字符的序列CRLF时,隔离的CR和LF字符不会指示换行符。
例如,模式/^ abc $/与多行模式下的主题字符串“def \nabc”(其中\n代表换行符)匹配,但不以其他方式。所以,这是在单行模式固定模式,因为所有的分支开始^不是在多行模式下锚,以及匹配抑扬有可能当争论开始偏移
的run/3
非零。dollar_endonly
如果multiline
设置,选项将被忽略。
请注意,序列\A,\Z和\z可用于在两种模式下匹配主题的开始和结束。如果一个模式的所有分支都以\A开始,它总是被锚定,无论是否multiline
设置。
Full Stop (Period, Dot)和\N
在字符类外部,模式中的点与主题字符串中的任何字符相匹配,但默认情况下表示行结束的字符除外。
当一行结尾被定义为单个字符时,点不匹配该字符。当使用双字符序列CRLF时,如果紧跟着LF,则点不匹配CR,否则匹配所有字符(包括隔离的CR和LF)。当任何Unicode行结尾被识别时,点不匹配CR,LF或任何其他行尾字符。
关于换行符的点行为可以改变。如果dotall
设置了选项,则点无匹配地匹配任何字符。如果主题字符串中存在双字符序列CRLF,则需要两个点来匹配它。
点的处理完全独立于回音和美元的处理,唯一的关系是两者都涉及换行符。Dot在角色类中没有特殊含义。
转义序列\N的行为像一个点,除了它不受选项影响PCRE_DOTALL
。也就是说,它匹配除了表示行尾之外的任何字符。Perl也使用\N来按名称匹配字符,但PCRE不支持这一点。
匹配单个数据单元
在字符类外部,转义序列\C匹配任何数据单元,无论是否设置了UTF模式。一个数据单位是一个字节。与点不同,\C总是匹配换行符。该功能在Perl中提供,以匹配UTF-8模式下的单个字节,但尚不清楚它如何有用。由于\C将字符分解为单独的数据单元,因此在UTF模式下将一个单元与\C匹配意味着剩余的字符串可能以畸形的UTF字符开头。这有未定义的结果,因为PCRE假定它处理有效的UTF字符串。
PCRE不允许\C以UTF模式出现在后向断言中(如下所述),因为这会使得不可能计算向后看的长度。
\C转义序列是最好的避免。但是,使用它避免UTF字符格式不正确的问题的一种方法是使用前视来检查下一个字符的长度,如下面的模式,它可以与UTF-8字符串一起使用(忽略空格和行休息时间):
(?| (?=[\x00-\x7f])(\C) |
(?=[\x80-\x{7ff}])(\C)(\C) |
(?=[\x{800}-\x{ffff}])(\C)(\C)(\C) |
(?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
以(?|)为开头的组(?)重置每个备选中的捕获括号(参见章节Duplicate Subpattern Numbers
)。每个分支开始处的断言检查下一个UTF-8字符的值,其编码使用1,2,3或4个字节,然后字符的单个字节被适当数量的组捕获。
方括号和字符类
开放方括号引入一个字符类,由一个方括号结束。自动关闭方括号在默认情况下并不特殊。但是,如果PCRE_JAVASCRIPT_COMPAT
设置了选项,则单独的关闭方括号会导致编译时错误。如果作为类的成员需要方括号,则它应该是该类中的第一个数据字符(在初始回调之后(如果存在))或用反斜杠转义。
字符类与主题中的单个字符相匹配。在UTF模式下,字符可以多于一个数据单元。匹配的字符必须位于类定义的字符集中,除非类定义中的第一个字符是旋转字符,在这种情况下,主题字符不得在该类定义的集合中。如果需要作为类的成员使用旋风,请确保它不是第一个字符,或者使用反斜杠进行转义。
例如,字符类[aeiou]
匹配任何小写元音,而[^aeiou]
匹配任何不是小写元音的字符。请注意,一个回音仅仅是一个方便的标记,用于通过枚举那些不在列表中的字符来指定类中的字符。以旋律开始的课程不是一个断言; 它仍会消耗主题字符串中的字符,因此如果当前指针位于字符串的末尾,则会失败。
在UTF-8模式下,值> 255(0xffff)的字符可以作为数据单元的字符串包含在类中,或者使用\x {转义机制。
当设置无格式匹配时,类中的任何字母都表示它们的大写和小写版本。例如,一个无情的[aeiou]匹配“A”和“a”,[^aeiou]无情的不匹配“A”,但是一个案例版本会。在UTF模式下,PCRE总是理解数值小于256的字符的概念,因此总是可以进行无匹配匹配。对于具有较高值的字符,仅当PCRE编译为Unicode属性支持时才支持case的概念。如果要在字符> =的UTF模式下使用无匹配匹配,请确保PCRE使用Unicode属性支持和UTF支持进行编译。
字符可以表示换行符匹配字符类,无论行结束序列是在使用时都从来没有在任何特殊的方式处理,并选择任何设置PCRE_DOTALL
和PCRE_MULTILINE
使用。像^这样的类总是匹配这些字符中的一个。
减号(连字符)可用于指定字符类中的字符范围。例如,dm匹配d和m之间的任何字母,包括在内。如果班级中需要减号字符,则必须使用反斜线进行转义,或者出现在不能被解释为指示范围的位置,通常作为班级中的第一个或最后一个字符,或紧接在某个范围之后。例如,bdz匹配范围b到d中的字母,连字符或z。
文字字符“]”不能是范围的结尾字符。W-46]这样的模式被解释为一个由两个字符(“W”和“ - ”)组成的类,后跟一个字符串“46”,所以它会匹配“W46”或“-46”。但是,如果“]”用反斜杠转义,它将被解释为范围的结尾,所以W-] 46被解释为一个包含一个范围后跟另外两个字符的类。“]”的八进制或十六进制表示也可用于结束一个范围。
如果POSIX字符类(见下文)或定义单个字符的转义序列以外的转义序列出现在预期范围结尾字符的位置,则会生成错误。例如,z- \ xff是有效的,但是A- \ d和[A-:digit:]不是。
范围以字符值的整理顺序操作。它们也可以用于数字指定的字符,例如\000- \037。范围可以包含对当前模式有效的任何字符。
如果在设置无格式匹配时使用包含字母的范围,则无论在哪种情况下都匹配字母。例如,Wc相当于无匹配的匹配。在非UTF模式下,如果正在使用法语区域设置的字符表,\ xc8- \ xcb在两种情况下都匹配带重音的E字符。在UTF模式下,PCRE只有在编码时使用Unicode属性支持才支持大于255的字符大小写的概念。
字符转义序列\d,\D,\h,\H,\p,\P,\s,\S,\v,\V,\w和\W可以出现在字符类中,他们与班级相匹配的字符。例如,\dABCDEF与任何十六进制数字匹配。在UTF模式下,选项ucp
会影响\d,\s,\w及其大写伙伴的含义,就像它们出现在字符类之外时一样(如Generic Character Types
前面部分所述)。转义序列\b在字符类中具有不同的含义;它匹配退格字符。序列\B,\N,\R和\X在字符类中并不特殊。像任何其他无法识别的转义序列一样,它们被视为文字字符“B”,“N”,“R”和“X”。
对于大写字符类型,可以方便地使用circumflex来指定比匹配的小写字符类型更受限制的字符集。例如,类^\W_匹配任何字母或数字,但不是下划线,而\w包含下划线。积极的人物类被认为是“某物或某物或......”,而一个否定的类别被认为是“不是某物而不是某物而不是......”。
字符类中只识别以下元字符:
- 反斜杠
- 连字符(只在可以解释为指定范围的地方)
- Circumflex(仅在开始时)
- 打开方括号(只有当它可以被解释为引入Posix类的名称,或者用于特殊的兼容性功能时;请参阅接下来的两节)
- 终合方架
但是,转义其他非字母数字字符不会造成任何伤害。
POSIX字符类
Perl支持字符类的Posix表示法。这使用封闭的方括号内的:和:所包含的名称。PCRE也支持这种表示法。例如,以下匹配“0”,“1”,任何字母字符或“%”:
[01[:alpha:]%]
以下是受支持的类名:
alnum
字母
和数字字母
字母
ASCII
字符代码0-127 空白
空间或制表仅CNTRL
控制字符位数
小数位数
(同\ d)图形
印刷字符,不包括空间低
小写字母
打印
打印
字符,包括空间PUNCT
印刷字符,不包括字母
,数字和空格
空格
空格
(与PCRE 8.34中的\ s相同)upper
大写字母
单词
“Word”字符(与\ w相同)xdigit
十六进制数字
默认的“空格”字符是HT(9),LF(10),VT(11),FF(12),CR(13)和空格(32)。如果特定于语言环境的匹配正在进行,则空格字符列表可能不同; 可能会有更少或更多。对于Perl兼容性,“Space”与\ s不同,它不包括VT。但是,Perl在版本5.18处更改,而PCRE在8.34版后面。“空间”和\现在匹配相同的一组字符。
“word”这个名字是一个Perl扩展,“blank”是Perl 5.8的一个GNU扩展。另一个Perl扩展是否定,在冒号后用^字符表示。例如,以下匹配“1”,“2”或任何非数字:
[12[:^digit:]]
PCRE(和Perl)也识别Posix语法.ch。和= ch =其中“ch”是“整理元素”,但不支持这些元素,并且遇到错误。
默认情况下,值> 255的字符不匹配任何Posix字符类。但是,如果PCRE_UCP传递给选项pcre_compile(),则会更改某些类,以便使用Unicode字符属性。这是通过用其他序列替换某些Posix类来实现的,如下所示:
:alnum:
Becomes \p{Xan}:alpha:
Becomes \p{L}:blank:
Becomes \h:digit:
Becomes \p{Nd}:lower:
Becomes \p{Ll}:space:
Becomes \p{Xps}:upper:
Becomes \p{Lu}:word:
Becomes \p{Xwd}
否定版本,例如:^ alpha :,使用\P而不是\p。其他三个POSIX类在UCP模式下专门处理:
*图表:
这与打印时具有标记页面的字形的字符匹配。在Unicode属性中,它将所有字符与L,M,N,P,S或Cf属性相匹配,但以下情况除外:
U+061 C
Arabic Letter Mark
U+180 E
蒙古元音分隔符
U+2066-U+2069
各种“isolate"s
:print:
这与以下相同的字符匹配:graph:加上不是控件的空格字符,即带有Zs属性的字符。
:punct:
这匹配具有Unicode P(标点符号)属性的所有字符,以及代码点小于128且具有S(符号)属性的字符。
其他POSIX类不变,只匹配码点小于128的字符。
字界兼容性特性
在4.4BSD Unix中包含的符合POSIX.2的库中,丑陋的语法[:<:]和[:>:]用于匹配“词的开始”和“词的结尾”。PCRE如下处理这些项目:
[:<:]
is converted to \b(?=\w)
[:>:]
is converted to \b(?<=\w)
只有这些确切的字符序列被识别。诸如[a:<:b]之类的序列会为无法识别的POSIX类名称引发错误。这种支持与Perl不兼容。它提供来帮助从其他环境迁移,并且最好不用于任何新的模式。请注意,\b匹配单词的开始和结尾(请参阅上面的“简单断言”),并且在Perl风格的模式中,前面或后面的字符通常显示需要的内容,而不需要使用的断言以便正确给出POSIX行为。
垂直杆
垂直栏字符用于分隔替代图案。例如,以下模式匹配“gilbert”或“sullivan”:
gilbert|sullivan
可以出现任意数量的替代方案,并允许使用空替代方案(匹配空字符串)。匹配过程依次尝试每个替代方案,从左到右,并使用成功的第一个替代方案。如果选项在子模式内(在章节中定义Subpatterns
),则“succeeds”意味着匹配子模式中剩余的主模式和备选模式。
内部选项设置
Perl兼容选项的设置caseless
,multiline
,dotall
,和extended
可以从图案内通过之间的Perl选项字母序列改变“(?”和“)”。选项字母如下所示:
i
For caseless
m
For multiline
s
For dotall
x
For extended
例如,(?im)
设置无格式,多行匹配。这些选项也可以通过在字母前加一个连字符来解除。的组合的设置和取消如(?im-sx)
,它设置caseless
和multiline
,而重置dotall
并且extended
,也是允许的。如果在连字符之前和之后出现一个字母,则该选项未设置。
PCRE特定的选项dupnames
,ungreedy
和extra
可以分别使用字符J,U和X以与Perl兼容选项相同的方式进行更改。
当其中一个选项更改发生在顶层(即不在子模式的括号内)时,更改将应用于随后的模式的其余部分。
子模式中的选项更改(请参见部分Subpatterns
)仅影响其后的子模式的那一部分。所以,以下匹配abc和aBc,并且没有其他字符串(假定caseless
不使用):
(a(?i)b)c
通过这种方式,可以使选项在模式的不同部分具有不同的设置。在一个备选方案中做出的任何更改都可以在同一个子模式内的后续分支中进行。例如:
(a(?i)b|c)
匹配“ab”,“aB”,“c”和“C”,但当匹配“C”时,在选项设置之前放弃第一个分支。这是因为选项设置的影响发生在编译时。否则会有一些奇怪的行为。
注
当调用编译或匹配函数时,应用程序可以设置其他PCRE特定的选项。有时模式可以包含特殊的前导序列,例如(* CRLF),以覆盖应用程序设置的内容或默认的内容。详情在Newline Sequences
前面的部分提供。
(* UTF8)和(* UCP)前导序列可用于设置UTF和Unicode属性模式。它们分别相当于设置选项unicode
和ucp
。(* UTF)序列是可以与任何库一起使用的通用版本。但是,应用程序可以设置选项never_utf
,从而锁定(* UTF)序列的使用。
子模式
子模式由圆括号(圆括号)分隔,可以嵌套。将模式的一部分转换为子模式会做两件事:
1.
它本地化了一套替代方案。例如,以下模式匹配"cataract", "caterpillar", or "cat":
cat(aract|erpillar|)
没有括号,它会匹配“cataract”,“erpillar”或空字符串。
2.
它将子模式设置为捕获子模式。也就是说,当完整模式匹配时,与子模式相匹配的主题字符串部分将通过返回值传递给调用者run/3
。
开头括号从左到右(从1开始)计数以获取拍摄子模式的数字。例如,如果字符串“the red king”与下列模式相匹配,则捕获的子串是“red king”,“red”和“king”,分别编号为1,2和3:
the ((red|white) (king|queen))
平括号完成两个功能并不总是有帮助的。通常一个分组子模式不需要捕获要求。如果左括号后面跟着问号和冒号,则子模式不执行任何捕获,并且在计算任何后续捕获子模式的数量时不计算。例如,如果字符串“the white queen”与以下模式相匹配,则捕获的子串是“white queen”和“queen”,并且编号为1和2:
the ((?:red|white) (king|queen))
捕获子模式的最大数量是65535。
作为方便的简写,如果在非捕获子模式开始时需要任何选项设置,选项字母可以出现在“?”之间 和“:”。因此,以下两种模式匹配相同的一组字符串:
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
由于可选分支从左到右进行尝试,并且直到达到子模式结束才重置选项,因此一个分支中的选项设置会影响后续分支,因此上述模式与“SUNDAY”和“Saturday”匹配。
重复子模式数
Perl 5.10引入了一个功能,其中子模式中的每个备选使用相同的数字来捕获括号。这样的子模式开始于(?|
并且本身是非捕获子模式。例如,请考虑以下模式:
(?|(Sat)ur|(Sun))day
由于这两个替代方案都属于一个(?|
组,因此两组捕获括号都被编号为1。因此,当模式匹配时,您可以查看捕获的第一个子字符串,无论哪个替代方法都匹配。当您想要捕捉多个替代品中的一个但不是全部时,该构造非常有用。在(?|
组内,括号的编号与往常一样,但编号在每个分支的开始处重置。子模式后面的任何捕获圆括号的数字开始于任何分支中使用的最高数字之后。以下示例来自Perl文档; 下面的数字显示捕获内容存储在哪个缓冲区中:
# before ---------------branch-reset----------- after
/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 2 3 2 3 4
对编号的子模式的反向引用使用任何子模式为该编号设置的最新值。以下模式匹配“abcabc”或“defdef”:
/(?|(abc)|(def))\1/
相反,调用子编号子模式的子程序始终引用模式中具有给定编号的第一个子程序。以下模式匹配“abcabc”或“defabc”:
/(?|(abc)|(def))(?1)/
如果具有匹配的子模式的条件测试引用非唯一编号,则如果该编号的任何子模式匹配,则测试为真。
使用这种“branch reset”功能的另一种方法是使用重复命名的子模式,如下一节所述。
命名子模式
通过数字识别圆括号很简单,但很难追踪复杂正则表达式中的数字。另外,如果表达式被修改,数字可以改变。为了解决这个难题,PCRE支持子模式的命名。在版本5.10之前,这个特性并没有被添加到Perl中。Python早期有这个功能,而PCRE在4.0版本中使用Python语法引入了它。PCRE现在支持Perl和Python语法。Perl允许编号相同的子模式具有不同的名称,但PCRE不会。
在PCRE中,可以通过三种方式之一来命名子模式:(?<name>...)或者(?'name'...)像在Perl中一样,或者(?P<name>...)在Python中。从模式的其他部分捕获括号的引用,例如后向引用,递归和条件可以通过名称和编号进行。
名称最多由32个字母数字字符和下划线组成,但必须以非数字开头。命名捕获圆括号仍然分配数字以及名称,就好像名称不存在一样。capture
规范run/3
,如果他们出现在正则表达式中可以使用指定的值。
默认情况下,名称在模式中必须是唯一的,但是可以通过dupnames
在编译时设置选项来放宽此约束。(对于具有相同编号的子模式,总是允许使用重复名称,如前一节中所述)。重复名称对于只有一个命名圆括号的实例可以匹配的模式很有用。假设你想匹配一个工作日的名字,或者是一个3个字母的缩写或者是全名,并且在这两种情况下你都想提取缩写。以下模式(忽略换行符)可以完成这项工作:
(?<DN>Mon|Fri|Sun)(?:day)?|
(?<DN>Tue)(?:sday)?|
(?<DN>Wed)(?:nesday)?|
(?<DN>Thu)(?:rsday)?|
(?<DN>Sat)(?:urday)?
有五个捕获子串,但只有一个是在比赛后设置的。(解决这个问题的另一种方法是使用“branch reset”子模式,如前一节所述)。
为了捕获名称不唯一的命名子模式run/3
,如果values
在capture
语句的部分中指定了名称,则返回第一个匹配事件(从主题中的从左到右计数)。该all_names
捕获值以同样的方式所有的名字相匹配。
注
您不能使用不同的名称来区分具有相同编号的两个子模式,因为PCRE在匹配时仅使用数字。由于这个原因,如果为具有相同编号的子模式指定了不同的名称,则在编译时会给出错误。但是,即使dupnames
未设置,也可以为具有相同编号的子模式指定相同的名称。
重复
重复是由量词指定的,它可以跟随下列任何一项:
- 文字数据字符
- 点元字符
- \C转义序列
- \X转义序列
- \R转义序列
- 与单个字符匹配的转义符,如\d或\pl
- 字符类
- 反向参考(请参阅下一部分)
- 带括号的子模式(包括断言)
- 对子模式的子程序调用(递归或其他)
一般重复量词通过在逗号分隔的大括号(大括号)中给出两个数字来指定允许匹配的最小和最大数量。数字必须小于65536,第一个必须小于或等于第二个。例如,以下匹配“zz”,“zzz”或“zzzz”:
z{2,4}
单独的右大括号不是特殊字符。如果第二个数字被省略,但逗号存在,则没有上限。如果省略了第二个数字和逗号,则量词将指定所需匹配的确切数量。因此,以下匹配至少三个连续的元音,但可以匹配更多:
[aeiou]{3,}
以下数字正好匹配八位数:
\d{8}
在不允许使用量词的位置显示一个开头的大括号,或者与量词的语法不匹配的开头大括号被视为文字字符。例如,{,6}不是一个量词,而是一个由四个字符组成的字符串。
在Unicode模式下,量词适用于字符而不是单个数据单元。因此,例如,\x {100} {2}匹配两个字符,每个字符由UTF-8字符串中的2字节序列表示。类似地,\X {3}匹配三个Unicode扩展字形群集,每个群集可以有很多数据单元(并且它们可以具有不同的长度)。
量词{0}是允许的,导致表达式的行为就好像先前的项目和量词不存在一样。这对于从模式中的其他地方引用为子例程的子模式很有用(但另请参见部分Defining Subpatterns for Use by Reference Only
)。除了具有{0}量词的子模式之外的项目在编译模式中被省略。
为方便起见,三种最常用的量词具有单字符缩写:
*
Equivalent to {0,}+
Equivalent to {1,}?
Equivalent to {0,1}
无限循环可以通过遵循一个子模式来构造,该子模式可以不匹配没有上限的量词的字符,例如:
(a?)*
早期版本的Perl和PCRE用于在编译时为这些模式提供错误。但是,由于有些情况下可能有用,现在可以接受这种模式。但是,如果任何重复的子模式都不匹配任何字符,则循环将被强制中断。
默认情况下,量词是“贪婪的”,即它们尽可能匹配(达到允许的最大次数),而不会导致剩余的模式失败。这给出了问题的典型例子是试图在C程序中匹配注释。这些出现在/ *和* /之间。在评论中,可以出现个别*和/字符。尝试通过应用模式来匹配C注释
/\*.*\*/
到字符串
/* first comment */ not comment /* second comment */
失败,因为它匹配整个字符串,因为*项目的贪婪。
但是,如果一个量词后跟一个问号,它就不再是贪婪的了,而是匹配最小的可能次数,所以下面的模式用C注释做了正确的事情:
/\*.*?\*/
各种量词的含义并没有改变,只有首选的匹配数量。不要将问号的使用与其作为量词本身的用法相混淆。由于它有两个用途,它有时可能会翻倍,如英寸
\d??\d
它按照偏好匹配一个数字,但如果这是剩余模式匹配的唯一方式,则可匹配两个数字。
如果ungreedy
设置了选项(在Perl中不可用的选项),默认情况下量词不是贪婪的,但可以通过使用问号跟随它们来使单个的贪婪成为贪婪。也就是说,它反转了默认行为。
当加括号的子模式的最小重复次数> 1或最大值有限时,编译模式需要更多内存,与最小或最大值的大小成比例。
如果模式以.*或.{0,}和option dotall
(相当于Perl选项/s
)开头,因此允许点匹配换行符,则模式被隐式锚定,因为无论如何针对主题中的每个字符位置串。因此,在第一次之后的任何位置重试整场比赛没有意义。PCRE通常对待这种模式,就好像它在前面是\ A。
在已知主题字符串不包含换行符的情况下,值得设置dotall
以获得此优化,或者使用^来明确指示锚定。
但是,有些情况下不能使用优化。如果。*在捕获模式中其他位置的后向引用的主题的括号内,则在稍后一次成功时,开始处的匹配可能会失败。考虑一下,例如:
(.*)abc\1
如果主题是“xyz123abc123”,则匹配点是第四个字符。因此,这种模式并不是隐含的。
隐式锚定未应用的另一种情况是,前导。*在原子组内。再一次,一开始的比赛可能会失败,在稍后的比赛成功。考虑以下模式:
(?>.*?a)b
它与主题“aab”中的“ab”匹配。使用回溯控制动词(* PRUNE)和(* SKIP)也会禁用此优化。
当重复捕获子模式时,捕获的值是匹配最终迭代的子字符串。例如,之后
(tweedle[dume]{3}\s*)+
已匹配“tweedledum tweedledee”,捕获的子字符串的值是“tweedledee”。但是,如果存在嵌套的捕获子模式,则可以在之前的迭代中设置相应的捕获值。例如,之后
/(a|(b))+/
匹配“ABA”,第二个捕获子字符串的值是“b”。
原子分组和占有量词
在最大化(“greedy”)和最小化(“非ungreedy”或“lazy”)重复的情况下,通常会导致对重复项目进行重新评估,以查看是否有不同重复次数允许剩余模式匹配。有时候,防止这种情况是有用的,或者改变匹配的性质,或者当模式的作者知道没有意义进行时,使它比其他情况下更早失败。
例如,当应用于以下主题行时,请考虑模式\d+foo:
123456bar
在匹配所有六位数字后,如果匹配“foo”失败,匹配器的正常操作是再次尝试,只有五个数字匹配项目\ d +,然后是四个,依此类推,最终失败。“原子分组”(取自杰弗里弗里德尔的书中的一个术语)提供了用于指定一旦子模式匹配的方法,就不会以这种方式重新评估。
如果在前面的例子中使用了原子分组,匹配器会在第一次无法匹配“foo”时立即放弃。符号是一种特殊的括号,从(?>下面的例子开始:
(?>\d+)foo
这种括号一旦匹配就“locks up”它所包含的模式部分,并且阻止进一步进入模式的失败回溯到其中。但是,回溯到之前的项目,正常工作。
另一种描述是,如果锚定在主题字符串中的当前点,则此类型的子模式与相同的独立模式匹配的字符串匹配。
原子分组子模式不捕获子模式。简单的例子,如上面的例子,可以被认为是一个最大化的重复,它必须吞下它所能做的一切。那么,\d +和\d+?都是准备调整它们匹配的数字以使其余模式匹配,(?>\d+)只能匹配整个数字序列。
通常原子组可以包含任何复杂的子模式,并且可以嵌套。但是,如上例所示,当原子组的子模式只是单个重复项时,可以使用称为“所有格量词”的简单符号。这由量词后面的一个额外的+字符组成。使用这个符号,前面的例子可以被重写为
\d++foo
请注意,所有格量词可以用于整个组,例如:
(abc|xyz){2,3}+
拥有量词永远是贪婪的;选项的设置ungreedy
被忽略。它们是简单形式的原子团体的便利标记。然而,所有格量词和等价原子组的含义没有区别,但可能存在性能差异;占有量词可能稍微快一点。
所有格量词语法是对Perl 5.8语法的扩展。杰弗里弗里德尔在他的书的第一版中提出了这个想法(和名字)。Mike McCloskey喜欢它,所以在他构建Sun Java包时实现了它,而PCRE从那里复制了它。它最终在5.10版本中找到了进入Perl的途径。
PCRE具有自动“拥有”某些简单模式构造的优化。例如,序列A+B被视为A++B,因为当B必须跟随时,没有点回溯到A:s序列中。
当一个模式在一个子模式中包含无限次重复时,它本身可以重复无限次数,使用原子组是避免一些失败的匹配需要很长时间的唯一方法。模式
(\D+|<\d+>)*[!?]
匹配无限数量的由非数字组成的子字符串,或匹配<>中的数字,然后是!要么 ?。当它匹配时,它运行得很快。但是,如果它适用于
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
报告失败之前需要很长时间。这是因为字符串可以通过多种方式在内部\D+重复和外部重复之间进行划分,并且都必须尝试。(这个例子在最后使用!?而不是单个字符,因为PCRE和Perl都有一个优化,当单个字符被使用时允许快速失败,他们记得匹配所需的最后一个字符,并且失败如果该模式被改变以便它使用原子组,如下所示,则不能破坏非数字序列,并且快速失败:
((?>\D+)|<\d+>)*[!?]
反向引用
在字符类之外,反斜杠后接数字> 0(可能还有其他数字)是对模式中较早捕获子模式(即其左侧)的反向引用,前提是有许多先前的捕获左括号。
但是,如果反斜杠后面的十进制数字小于10,则始终将其作为反参考,并且仅在整个模式中没有多少捕获左括号时才会导致错误。也就是说,被引用的圆括号不需要在数字<10的引用的左侧。当涉及重复并且右侧的子模式已经参与了该类型的“向后引用”时,较早的迭代。
由于像\50这样的序列被解释为以八进制定义的字符,所以使用此语法不可能对数字为10或更多的子模式使用数字“前向回参考”。有关反斜杠后数字处理的更多详细信息,请参见Non-Printing Characters
前面的部分。使用带括号的名称时不存在这样的问题。任何子模式的反向引用都可以使用带括号的括号(见下文)。
另一种避免使用反斜杠后数字固有歧义的方法是使用\ g转义序列。这个转义后面必须跟随一个无符号数或负数,可选地用大括号括起来。以下示例是相同的:
(ring), \1
(ring), \g1
(ring), \g{1}
无符号数字指定绝对引用,而不存在旧语法中的歧义。当文字数字跟随引用时,它也很有用。负数是相对的引用。考虑以下示例:
(abc(def)ghi)\g{-1}
\g{-1}序列是对\g之前最近开始的捕获子模式的引用,即在本例中相当于\2。同样,\g{-2} 将等同于\ 1。相对引用的使用可以在长模式中有用,也可以在通过在自身内部连接包含引用的片段创建的模式中使用。
反向引用匹配与当前主题字符串中的捕获子模式匹配的任何内容,而不是匹配子模式本身的任何内容(部分Subpattern as Subroutines
描述了这样做的一种方式)。所以,下面的模式匹配“sense and sensibility”和“response and responsibility”,但不符合“sense and responsibility”:
(sens|respons)e and \1ibility
如果在回参考时有效的情况下,字母的情况是相关的。例如,以下匹配“rah rah”和“RAH RAH”,但不匹配“RAH rah”,尽管原始捕获子模式无条件匹配:
((?i)rah)\s+\1
有很多不同的方式来回写对已命名子模式的引用。在.NET语法\k{name}和Perl的语法\k<name>或\k'name'支持,因为是Python语法(?P=name)。Perl 5.10中统一的后向引用语法,其中\ g可以用于数字引用和命名引用,也支持。前面的例子可以通过以下方式重写:
(?<p1>(?i)rah)\s+\k<p1>
(?'p1'(?i)rah)\s+\k{p1}
(?P<p1>(?i)rah)\s+(?P=p1)
(?<p1>(?i)rah)\s+\g{p1}
由名称引用的子模式可以出现在引用之前或之后的模式中。
对同一个子模式可以有多个返回引用。如果子模式没有用于特定的匹配,则任何对它的反向引用都会失败。例如,如果它开始匹配“a”而不是“bc”,则以下模式总是失败:
(a|(bc))\2
由于模式中可能有许多捕捉括号,因此反斜杠后面的所有数字都将作为潜在后向参考号的一部分。如果模式以数字字符继续,则必须使用某个分隔符来终止反向引用。如果extended
设置了选项,则可以是空格。否则,Comments
可以使用空注释(请参阅部分)。
递归反向引用
在第一次使用子模式时,它引用的括号内的后向引用失败,因此,例如(a\1)永远不匹配。但是,这样的引用在重复的子模式中可能很有用。例如,以下模式匹配任意数量的“a”和“aba”,“ababbaa”等等:
(a|b\1)+
在子模式的每次迭代中,反向引用匹配与先前迭代对应的字符串。为了使其工作,模式必须是第一次迭代不需要与后向引用匹配。这可以使用交替来完成,如上例所示,或者使用最小为零的量词。
此类型的反向引用会将它们引用的组视为原子组。一旦整个组被匹配,随后的匹配失败不会导致回溯到组中。
断言
断言是对不消耗任何字符的当前匹配点之后或之前的字符的测试。前面的部分描述了编码为\b、\B、\A、\G、\Z、\z、^和$的简单断言。
更复杂的断言被编码为子模式。有两种:在主题字符串中的当前位置前面的那些,以及在它后面的那些。断言子模式以正常方式匹配,除了它不会导致当前匹配位置被更改。
断言子模式不捕获子模式。如果这样的断言包含捕获其中的子模式,则这些被计数用于在整个模式中对捕获子模式进行编号。但是,子字符串捕获仅适用于肯定的断言。(Perl有时但并非总是在负面断言中执行捕获。)
警告
如果包含一个或多个捕获子模式的肯定断言成功,但在模式中稍后匹配失败会导致对此断言的回溯,则断言中的捕获仅在未设置较高编号的捕获时才会重置。不幸的是,这是目前实施的一个根本限制,并且由于PCRE1目前处于维修状态,所以不可能改变。
为了与Perl兼容,可以重复断言子模式。然而,多次断言相同的东西是没有意义的,捕获括号的副作用有时也会有用。实际上,只有三个案件:
- 如果量词是{0},那么在匹配过程中断言从不遵守。但是,它可以包含通过子例程机制从别处调用的内部捕获括号组。
- 如果量词为{0,n},其中n>0,则将其视为{0,1}。在运行时,使用或不使用断言来尝试其余模式匹配,顺序取决于量词的贪婪程度。
- 如果最小重大于0,则量化符被忽略。当匹配期间遇到断言时,断言只服从一次。
- (* THEN)是最弱的,在下一个选项中进行比赛。
- (* PRUNE)接下来,在当前起始位置失败匹配,但允许前进到下一个字符(对于未锚定的模式)。
- (* SKIP)是相似的,只是前进可以不止一个字符。
- (* COMMIT)是最强的,导致整个比赛失败。
- (* FAIL)在子模式中被称为子例程有其正常的效果:它强制立即回溯。
- (* ACCEPT)作为子例程调用的子模式会导致子例程匹配成功,而无需进一步处理。然后在子程序调用之后继续匹配。
- (* COMMIT),(* SKIP)和(* PRUNE)在调用子程序的子模式中导致子程序匹配失败。
- (* THEN)跳转到子模式中具有替代方案的最内部封闭组中的下一个替代方案。如果子模式内没有这样的组,则(* THEN)会导致子程序匹配失败。