当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


erlang run(Subject, RE, Options)用法及代码示例


run(Subject, RE, Options) ->
       {match, Captured} | match | nomatch | {error, ErrType}
类型:
Subject = iodata() | unicode:charlist()
RE = mp() | iodata() | unicode:charlist()
Options = [Option]
Option = 
    anchored | global | notbol | noteol | notempty |
    notempty_atstart | report_errors |
    {offset, integer() >= 0} |
    {match_limit, integer() >= 0} |
    {match_limit_recursion, integer() >= 0} |
    {newline, NLSpec :: nl_spec()} |
    bsr_anycrlf | bsr_unicode |
    {capture, ValueSpec} |
    {capture, ValueSpec, Type} |
    CompileOpt
Type = index | list | binary
ValueSpec = 
    all | all_but_first | all_names | first | none | ValueList
ValueList = [ValueID]
ValueID = integer() | string() | atom()
CompileOpt = compile_option()
参看 compile/2.
Captured = [CaptureData] | [[CaptureData]]
CaptureData = 
    {integer(), integer()} | ListConversionData | binary()
ListConversionData = 
 string() |
    {error, string(), binary()} |
    {incomplete, string(), binary()}
ErrType = 
    match_limit | match_limit_recursion | {compile, CompileErr}
CompileErr = 
    {ErrString :: string(), Position :: integer() >= 0}

执行正则表达式匹配,并返回 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_limitmatch_limit_recursion ),或者指示编译错误,其中错误元组的格式为 {error, {compile, CompileErr}} 。请注意,如果未指定选项 report_errors,则该函数永远不会返回错误元组,而是将编译错误报告为 badarg 异常,并将由于超出匹配限制而失败的匹配简单地报告为 nomatch

以下选项与执行相关:


anchored

run/3 限制为在第一个匹配位置进行匹配。如果模式是使用 anchored 编译的,或者结果是凭借其内容进行锚定的,则无法在匹配时将其取消锚定,因此没有 unanchored 选项。


global

实现全局(重复)搜索(Perl 中的标志 g)。每个匹配项都作为单独的 list() 返回,其中包含特定匹配项和任何匹配子表达式(或由选项 capture 指定)。因此,返回值的 Captured 部分是 list()list() ,当此选项已指定。

选项 global 与匹配空字符串的正则表达式的交互让一些用户感到惊讶。当指定选项 global 时, run/3 以与 Perl 相同的方式处理空匹配:也会使用选项 [anchored, notempty_atstart] 重试任意点的零长度匹配。如果该搜索给出的结果长度 > 0,则包含该结果。例子:

re:run("cat","(|at)",[global]).

执行以下匹配:


At offset 0

正则表达式 (|at) 首先匹配字符串 cat 的初始位置,给出结果集 [{0,0},{0,0}] (第二个 {0,0} 是因为括号标记的子表达式)。由于比赛长度为 0,我们还没有进入下一个位置。



At offset 0 with [anchored, notempty_atstart]

使用选项 [anchored, notempty_atstart] 在同一位置重试搜索,这不会给出任何更长长度的有趣结果,因此搜索位置前进到下一个字符 ( a )。


At offset 1

搜索结果为 [{1,0},{1,0}] ,因此也会使用额外选项重复此搜索。



At offset 1 with [anchored, notempty_atstart]

找到替代方案 ab,结果为 [{1,2},{1,2}]。结果将添加到结果列表中,并且搜索字符串中的位置将前进两步。


At offset 3

搜索再次匹配空字符串,给出 [{3,0},{3,0}]



At offset 1 with [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 没有直接等效于 notemptynotempty_atstart ,但它确实在 split() 函数中以及使用修饰符 /g 时对空字符串进行模式匹配。匹配空字符串后,可以通过首先在 notempty_atstartanchored 相同的偏移量处再次尝试匹配来模拟 Perl 行为,然后,如果失败,则通过提前起始偏移量(见下文)并尝试普通的再次比赛。


notbol

指定主题字符串的第一个字符不是行的开头,因此其前面的扬抑元字符不匹配。在没有multiline(编译时)的情况下设置此项会导致扬抑符永远不会匹配。此选项仅影响扬抑符元字符的行为。它不影响\A。


noteol

指定主题字符串的结尾不是行的结尾,因此美元元字符不匹配它,也不匹配它之前的换行符(多行模式除外)。在没有multiline(编译时)的情况下设置此值会导致美元永远不匹配。此选项仅影响美元元字符的行为。它不影响 \Z 或 \z。


report_errors

更好地控制 run/3 中的错误处理。指定后,编译错误(如果尚未编译正则表达式)和运行时错误将作为错误元组显式返回。

以下是可能的运行时错误:


match_limit

PCRE 库对内部匹配函数的调用次数设置了限制。在为 Erlang 编译的库中默认为 10,000,000。如果返回{error, match_limit},则正则表达式的执行已达到此限制。这通常被视为 nomatch ,这是发生这种情况时的默认返回值,但通过指定 report_errors ,当由于内部调用过多而导致匹配失败时,您会收到通知。


match_limit_recursion

这个错误非常类似于match_limit,但是当 PCRE 的内部匹配函数 "recursively" 调用次数多于match_limit_recursionlimit,默认也是 10,000,000。请注意,只要match_limitmatch_limit_default值保留为默认值,match_limit_recursion错误不会发生,因为match_limit错误发生在这之前(每次递归调用也是一次调用,但反之则不然)。但是,这两个限制都可以通过直接在正则表达式字符串中设置限制来更改(请参阅PCRE 正则表达式详细信息)或通过指定选项run/3.

重要的是要理解,限制匹配时所谓的 "recursion" 并不是 Erlang 机器的 C 堆栈或 Erlang 进程堆栈上的递归。编译到 Erlang VM 中的 PCRE 版本使用机器 "heap" 内存来存储必须在正则表达式匹配中的递归中保留的值。


{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 中。

注意

该选项绝不会影响 Erlang VM 的“长时间运行 BIF”的执行。 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 VM 使用 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

换行符由 two-character 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-specific 换行符。 (覆盖编译选项。)


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

除第一个匹配子模式之外的所有子模式,即所有显式捕获的子模式,但不是主题字符串的完整匹配部分。如果正则表达式作为一个整体与主题的大部分相匹配,但您感兴趣的部分位于显式捕获的子模式中,则这非常有用。如果返回类型是 listbinary ,不返回您不感兴趣的子模式是一个很好的优化方法。


none

不返回匹配的子模式,匹配成功时将单个原子 match 作为函数的返回值,而不是 {match, list()} 返回。指定空列表会产生相同的行为。

值列表是要返回的子模式的索引列表,其中索引 0 表示所有模式,1 表示正则表达式中的第一个显式捕获子模式,依此类推。在正则表达式中使用命名的捕获子模式(见下文)时,可以使用 atom()string() 来指定要返回的子模式。例如,考虑正则表达式:

".*(abcd).*"

与字符串 "ABCabcdABC" 匹配,仅捕获 "abcd" 部分(第一个显式子模式):

re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).

该调用给出以下结果,因为第一个显式捕获的子模式是 "(abcd)",与主题中的 "abcd" 匹配,位于(从零开始)位置 3,长度为 4:

{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} ,但对于其他类型( binarylist ),值是空二进制或列表,分别。


Type

(可选)指定如何返回捕获的子字符串。如果省略,则使用默认值index

Type 可以是以下之一:


index

将捕获的子字符串作为主题字符串的字节索引对和主题中匹配字符串的长度返回(就好像主题字符串被展平了一样)iolist_to_binary(IoListOrBinary)或者 unicode:characters_to_binary/2匹配之前)。注意该选项unicode结果是面向字节的a 中的索引(可能是虚拟的)UTF-8编码二进制。字节索引元组{0,2}因此可以代表一个或两个字符unicode已生效。这看起来counter-intuitive,但被认为是最有效和最有用的方法。如果需要的话,返回列表可以得到更简单的代码。此返回类型是默认值。


list

以字符列表的形式返回匹配的子字符串(Erlangstring()s)。它选项unicode与正则表达式中的 \C 序列结合使用,捕获的子模式可以包含无效 UTF-8 的字节(\C 匹配字节,无论字符编码如何)。在这种情况下list捕获可以产生相同类型的元组characters_to_list(Data, InEncoding)可以返回,即带标签的三元组incomplete或者error、成功转换的字符以及转换为二进制的无效 UTF-8 尾部。最好的策略是在捕获列表时避免使用 \C 序列。


binary

以二进制形式返回匹配的子字符串。如果使用选项 unicode,则这些二进制文件采用 UTF-8 格式。如果 \C 序列与 unicode 一起使用,则二进制文件可能是无效的 UTF-8。

通常,当 typeindex 时,在匹配中未分配值的子模式将作为元组 {-1,0} 返回。对于其他返回类型,未分配的子模式分别作为空二进制或列表返回。考虑以下正则表达式:

".*((?<FOO>abdd)|a(..d)).*"

存在三个显式捕获子模式,其中左括号位置决定结果中的顺序,因此 ((?<FOO>abdd)|a(..d)) 是子模式索引 1,(?<FOO>abdd) 是子模式索引 2,(..d) 是子模式索引 3。当与以下匹配时 String :

"ABCabcdABC"

索引 2 处的子模式不匹配,因为字符串中不存在 "abdd" ,但完整模式匹配(因为替代 a(..d) )。因此,索引 2 处的子模式未分配,默认返回值为:

{match,[{0,10},{3,4},{-1,0},{4,3}]}

将捕获 Type 设置为 binary 给出:

{match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}

这里的空二进制文件 (<<>>) 表示未分配的子模式。在 binary 情况下,有关匹配的一些信息因此丢失,因为 <<>> 也可以是捕获的空字符串。

如果需要区分空匹配和不存在的子模式,请使用 type index 并转换为 Erlang 代码中的最终类型。

当指定选项 global 时,capture 规范会单独影响每个匹配,因此:

re:run("cacb","c(a|b)",[global,{capture,[1],list}]).

{match,[["a"],["b"]]}

有关仅影响编译步骤的选项的说明,请参见compile/2.

相关用法


注:本文由纯净天空筛选整理自erlang.org大神的英文原创作品 run(Subject, RE, Options) -> {match, Captured} | match | nomatch | {error, ErrType}。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。