正则表达式

IsMatchMatchMatchAll 函数 用于提取和验证文本中的模式。 他们使用的模式称为 正则表达式

正则表达式功能强大且用途广泛。 但是,它们有时可以显示为随机的标点符号序列。 本文没有描述正则表达式的所有方面,但在线提供了 wealth 的信息、教程和工具。

正则表达式有着悠久的历史,并且有多种编程语言版本。 每种编程语言都有自己的正则表达式方言,而且标准很少。 我们尽可能地努力让相同的正则表达式在所有 Power Fx 实现中给出相同的结果。 兼容性并不容易实现,因为 Power Fx 在 JavaScript 和 .NET 之上运行,它们有显着差异。 为了在不同的平台上运行, Power Fx 正则表达式使用了整个行业广泛支持的功能子集。

因此,一些在其他环境中工作的正则表达式可能会被阻止或需要调整 Power Fx。 当遇到不受支持的功能时,将报告创作时间错误。 这就是为什么正则表达式和选项必须是创作时间常量而不是动态的,例如在变量中提供。

备注

Power Apps 使用早期版本的 Power Fx 正则表达式,该版本的限制较少,但功能也较少。 MatchOptions.DotAllMatchOptions.FreeSpacing 不可用,并且 Match.Email Match.Hyphen 定义不同。 Unicode 代理对不被视为单个字符。 MatchOptions.NumberedSubMatches 是默认值。 此处描述的正则表达式版本即将在“ Power Apps V1.0 兼容性”开关下提供Power Fx 。

支持的功能

Power Fx 支持以下正则表达式功能,并附有有关行为与其他系统有何 Power Fx 不同的说明。

正则表达式必须是常量的,并且不能计算或存储在变量中。 & 支持运算符、字符串插值 $"{...}"以及具有常量参数的 the ConcatenateCharUniChar 函数。

文字字符

特性 Description
文字字符 可以直接插入任何 Unicode 字符, \除了, []^$.|?*+(){}和。 使用 MatchOptions.FreeSpacing# 和其他 \s 空格字符时,必须转义,因为它们具有不同的含义。
转义的文字字符 \ (反斜杠)后跟直接文字字符之一,例如 \? 插入问号。 \# 即使 \ 为了一致性而禁用了 MatchOptions.FreeSpacing 也可以使用。
十六进制和 Unicode 字符代码 \x20 恰好有两个十六进制数字, \u2028 恰好有四个十六进制数字,可用于高低代理。
Unicode 代码点 \u{01F47B} 最多有八位十六进制数字。 必须在 0 到 U+10FFFF 范围内,不能用于高或低代理。 如果大于 U+FFFF,可能会导致代理对(两个字符)。
回车 \r,与 Char(13)
换行符 \n,与 Char(10)
表单进给 \f,与 Char(12)
水平选项卡 \t,与 Char(9)

使用 \x or \u 代替。 字符的八进制代码(例如 \044 或是 \o{044} 不允许的),因为它们可能与编号的反向引用不一致。

\v 不受支持,因为它在正则表达式语言中是不明确的。 用于 \x0b 垂直选项卡或 [\x0b\f\r\n\x85\u2028\u2029] 垂直空格。

断言

断言与文本中的特定位置匹配,但不使用任何字符。

特性 Description
行首 ^,匹配文本的开头,如果使用 MatchOptions.Multiline ,则 匹配行的开头。
行尾 $,匹配文本的末尾,如果使用 MatchOptions.Multiline ,则 匹配行的末尾。
前瞻 (?=a) 并且 (?!a),为模式提前匹配。
后视 (?<=b) 并且 (?<!b),匹配在后面的模式。
断字符 \b 并且 \B,使用 Unicode 字母 [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}\p{Lm}]定义。

$ 匹配行尾,包括任何尾随 \r\n\r\n

前瞻和后视断言不能包含子匹配项或内部无限量词,也不能与外部量词一起使用。

字符类

特性 Description
.,匹配除和 \r except \n 使用 MatchOptions.DotAll 之外 的所有内容。
字符类 [abc] 字符列表, [a-fA-f0-9] 字符范围, [^a-z] 除了这些字符之外的所有内容。 字符类不能嵌套、减法或相交,并且许多标点符号不得连续出现两次(@@%%!!,等)。
单词字符 \w 以及 \W 使用 Unicode 字母 [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}\p{Lm}]定义。 \W 不能在负字符类中使用。
数字字符 \d 包括数字 09\p{Nd}\D 匹配除匹配的 \d字符之外的所有内容。 \D 不能在负字符类中使用。
空间字符 \s 包括空格字符 [ \t\n\x0b\f\r\x85\u2028\u2029\p{Z}]\S 它匹配除匹配的 \s字符之外的所有字符。 \S 不能在负字符类中使用。
Unicode 字符类别 \p{Ll} 匹配所有 Unicode 小写字母,而 \P{Ll} 匹配所有非 Unicode 小写字母。 \P{} 不能在负字符类中使用。

为了提高清晰度并避免歧义,方括号字符类比其他正则表达式语言更具限制性:

  • 文字连字符必须转义。 使用 [\-a] instead of [-a] 匹配 - or a
  • 必须转义开头方括号。 使用 [\[a] instead of [[] 匹配 [ or a
  • 除非它是第一个字符并表示否定,否则必须转义该字符。 使用 [a\^] instead of [a^] 匹配 ^ or a
  • 必须转义大括号。 用于 [\{\}] 匹配 {}
  • 不支持空字符类 [] 。 若要在字符类中包含右方括号,请转义它。

\p{} 支持的 \P{}Unicode 字符类别:

  • 字母: LLu,, LlLt,, LmLo
  • 标志: M,, MnMcMe
  • 数字: NNd,, NlNo
  • 标点符号: P,,,, PcPdPsPePiPfPo
  • 符号: SSm,, ScSkSo
  • 分隔符: ZZs,, ZlZp
  • Control 和 Format: CcCf,,而不支持其他 C 前缀类别。

\W\D\S\P{} 并且不能在否定字符类 [^...]中使用。 为了在某些平台上实现,这些负字符类被转换为其 Unicode 等效项,如果也被否定,这可能很难做到。

字符类不支持 U+10000 和 U+10FFFF 之间的 Unicode 字符(需要代理对)。

量词

特性 Description
贪婪零或一 ? 匹配 0 次或 1 次, 匹配量尽可能大
贪婪零或更多 * 匹配 0 次或多次, 匹配尽可能大
贪婪一个或多个 + 匹配一次或多次, 匹配尽可能大
贪婪至少 n {n,} 至少匹配 n 次, 匹配尽可能大 。 例如, a{3,} 匹配中的所有 aaaaa字符。
N 和 m 之间的贪婪 {n,m} n 次和 m 次之间的 匹配, 匹配量尽可能大 。 例如, a{1,3} 匹配的 aaaaa前三个字符。
懒惰零或一 ?? 匹配 0 次或 1 次, 匹配量尽可能小
惰性零或更多 *? 匹配 0 次或多次, 匹配量尽可能小
惰性一个或多个 +? 匹配一次或多次, 匹配尽可能小
懒惰至少 n {n,}? 至少匹配 n 次, 匹配尽可能小 。 例如, a{3,}? 仅匹配中的 aaaaa前三个字符。
N 和 m 之间的惰性 {n,m}? n 次和 m 次之间的 匹配, 匹配尽可能小 。 例如, a{1,3}? 仅匹配的 aaaaa第一个字符。
精确 n {n} 匹配 n 次,准确。 例如, a{3} 恰好匹配的 aaaaa三个字符。

不支持所有格量词。

混合子匹配和量词有局限性。 有关详细信息,请参阅 可能为空的子匹配项

特性 Description
组合 () 用于对要应用的量词的元素进行分组。 例如, (abc)+ 匹配 abcabc
Alternation a|b 匹配“a”或“b”,通常在组中使用。
命名子匹配和反向引用 (?<name>chars) 捕获名称为“ name引用”的 \k<name>子匹配项。 如果启用了 MatchOptions.NumberedSubMatches ,则 无法使用。
编号子匹配和反向引用 启用 MatchOptions.NumberedSubMatches (a) 捕获引用的 \1子匹配项。
非捕获组 (?:a),创建组,而不将结果捕获为命名或编号的子匹配项。 除非启用了 MatchOptions.NumberedSubMatches ,否则 所有组都不会捕获。

命名子匹配和编号子匹配不能一起使用。 默认情况下,命名子匹配项处于启用状态,并且为了清晰度和可维护性而首选,而标准捕获组则成为性能提高的非捕获组。 可以使用 MatchOptions.NumberedSubMatches 更改 此行为,该选项提供传统捕获组,但禁用命名捕获组。 某些实现以不同的方式处理编号和命名捕获组的混合,这就是不允许它的原因 Power Fx 。

不支持自引用捕获组,例如正则表达式 (a\1)

两个捕获组不能共享相同的名称,例如,不支持正则表达式 (?<id>\w+)|(?<id>\d+)

命名子匹配项的名称必须以字符开 \p{L} 头,或者 _,并且可以继续使用这些字符加号 \p{Nd}。 名称的长度限制为 62 个 UTF-16 代码单位。

也不支持对可能为空的子匹配项以及向后看或向前看中的子匹配项的反向引用。

一些实现提供了一个“显式捕获”选项来提高性能,这是不必要的 Power Fx ,因为它是默认的。 MatchOptions.NumberedSubMatches 禁用它并启用隐式编号的捕获。

混合子匹配和量词有局限性。 有关更多信息,请参阅 可能为空子匹配项

注释

特性 Description
内联注释 (?# comment here),将其作为注释忽略。 注释以下一个右括号结尾,即使注释中有左括号。

有关格式化和注释正则表达式的 alternative,请参阅 MatchOptions.FreeSpacing

内联选项

特性 Description
内联选项 (?im) 与使用 MatchOptions.IgnoreCase MatchOptions.Multiline 相同。 必须在正则表达式的开头设置。

支持的内联模式是 [imsx]。 这些分别对应 于 MatchOptions.IgnoreCaseMatchOptions.MultilineMatchOptions.DotAllMatchOptions.FreeSpacingn 也接受兼容性,但无效,因为它是默认值,并且与 MatchOptions.NumberedSubMatches 兼容。

内联选项不能用于禁用选项或设置子表达式的选项。

选项

匹配选项更改正则表达式匹配的行为。 有两种方法可以启用选项,只要没有冲突,就可以混合使用:

  • MatchOptions 枚举值作为第三个参数传递给 MatchMatchAllIsMatch。 例如 & ,选项可以与 Concatenate 运算符或 MatchOptions.DotAll & MatchOptions.FreeSpacing函数组合使用。 所有正则表达式函数都要求 MatchOptions 是常量值,不能计算或存储在变量中。
  • (?...) 正则表达式开头的前缀。 例如 (?...) ,选项可以与构造中的 (?sx)多个字母组合。 某些选项没有等效项 (?...) ,但可能有其他方法来获得相同的效果,例如 MatchOptions.BeginsWith 等效 ^ 于正则表达式开头的。

包含

使用 MatchOptions.Contains 启用 ,没有等效的正则表达式文本。 MatchOptions.Contains 是外部 Power Apps所有函数的默认值;MatchOptions.Complete Power Apps 是 IsMatch 默认值。

完成

分别在正则表达式的开头和开头使用 MatchOptions.Complete 或使用 and ^ 启用 $

BeginsWith

使用 MatchOptions.BeginsWith 启用 ,或 ^ 在正则表达式的开头和开头使用。

EndsWith

使用 MatchOptions.EndsWith 启用 或在正则表达式末尾使用 $

点全部

使用 MatchOptions.DotAll (?s) 在正则表达式的开头启用。

通常,点 . 运算符匹配除换行符 [\n\x0b\f\r\x85\u2028\u2029]之外的所有字符。 使用 DotAll 修饰符, 所有字符都匹配,包括换行符。

在此示例中,仅匹配“Hello”,因为默认情况下不 . 匹配换行符:

Trim( Match( "Hello
              World", ".*" ).FullMatch )
// returns 
// "Hello"

但是如果我们添加 DotAll 修饰符,则换行符和所有后续字符都匹配:

Trim( Match( "Hello
              World", ".*", MatchOptions.DotAll ).FullMatch )
// returns 
// "Hello
// World"

自由空间

使用 MatchOptions.FreeSpacing (?x) 在正则表达式的开头启用。

自由间距使阅读和维护复杂的正则表达式变得更加容易。 规则很简单:

  • 正则表达式中将忽略空格字符,包括所有匹配 \s的字符。 如果需要匹配空格,请使用 \s\ \t,, \r\n
  • # 开始一个注释,一直持续到行尾。 它和跟随下一个换行符的所有字符(没有 MatchOptions.DotAll .字符)都将被忽略。
  • 这些更改中不包括字符类。 空间角色并 # 像往常一样行事。 例如, IsMatch( "a#b c", "(?x)a[ #]b[ #]c" ) 返回 true。 某些正则表达式语言包含自由间距的字符类,或提供包含它们的选项,但 Power Fx 没有。

例如,下面是一个用于匹配 ISO 8601 日期时间的复杂正则表达式:

IsMatch( 
    "2025-01-17T19:38:49+0000",
    "^\d{4}-(0\d|1[012])-([012]\d|3[01])(T([01]\d|2[0123]):[0-5]\d(:[0-5]\d(\.\d{3})?)?(Z|[\-+]\d{4}))?$"
)
// returns true

这是相同的正则表达式,具有自由间距,使用多行、组缩进和正则表达式注释,使该版本更易于理解、验证和维护。

IsMatch( "2025-01-17T19:38:49+0000", 
    "(?x)                 # enables free spacing, must be very first
    ^                     # matches from beginning of text
    \d{4}                 # year (0000-9999)
    -(0\d|1[012])         # month (00-12)
    -([012]\d|3[01])      # day (00-31, range not checked against month)
    (T([01]\d|2[0123])    # optional time, starting with hours (00-23)
      :[0-5]\d            # minutes (00-59)
      (:[0-5]\d           # optional seconds (00-59)
        (\.\d{3})?        # optional milliseconds (000-999)
      )?
      (Z|[\-+]\d{4})      # time zone
    )?
    $                     # matches to end of text
    "
)
// returns true

IgnoreCase

使用 MatchOptions.IgnoreCase (?i) 在正则表达式的开头启用。

匹配字母中的文本,不区分大小写:大写字母匹配小写字母,小写字母匹配大写字母。

例如:

IsMatch( "HELLO!", "hello", MatchOptions.IgnoreCase )
// returns true

IsMatch( "file://c:/temp/info.txt", "^FILE://", MatchOptions.IgnoreCase )
// returns true

大部分部分或 Power Fx 都有文化意识,但这里没有。 使用文化不变匹配是正则表达式的行业标准,包括在 JavaScript 和 Perl 中。 在匹配系统资源的第二个示例中,它很有用,例如, tr-TR 区域性 I 不是大写等效项 i

如果需要区分大小写的区域性感知匹配,请改用带有匹配字符的字符类,例如 [Hh][Ee][Ll][Ll][Oo] 对于第一个示例。

多行

使用 MatchOptions.Multiline (?m) 在正则表达式的开头启用。

通常, ^$ 点与输入文本的开头和开头匹配。 使用“多行” 修饰符时,这些锚点将匹配输入文本中行的开头和结尾,其中每行以输入的,\r,或结尾结 \n\r\n尾。 例如:

MatchAll( "Hello" & Char(13) & Char(10) & "World", "^.+$" )
// returns 
// "Hello"

预定义模式

预定义模式允许您匹配一组字符中的一个或多个字符的序列。 使用 string-concatenation 运算符 & 文本字符串与 Match 枚举的 成员组合在一起:

Match 枚举 Description 正则表达式
任何 匹配任何字符。 .
逗点 匹配逗号 , ,
数字 匹配个位数(0 通过 9 和其他成员 \p{Nd})。 \d
电子邮件 匹配包含“at”符号(@)的电子邮件地址和包含至少一个点(). 的域名,由空格和标点符号分隔。 见注释
连字号 匹配连字符。 - 见注释
左帕伦 匹配左括号 ( \(
匹配一个字母。 \p{L}
多位数 匹配一个或多个数字。 \d+
多个字母 匹配一个或多个字母。 \p{L}+
MultipleNonSpaces 匹配不包含空白(不是空格、制表符或换行符)的一个或多个字符。 \S+
多空间 匹配可间断(包含空格、制表符或换行符)的一个或多个字符。 \s+
非空间 匹配不包含空白的单个字符。 \S
可选数字 配零个、一个或多个数字。 \d*
可选字母 匹配零个、一个或多个字母。 \p{L}*
可选非空格 匹配不包含空白的零个、一个或多个字符。 \S*
可选空间 匹配包含空白的零个、一个或多个字符。 \s*
Period 匹配句点或点 . \.
右帕伦 与右括号 )匹配。 \)
空间 匹配包含空白的字符。 \s
Tab 匹配制表符。 \t

例如,模式 “A”和 Match.MultipleDigits 匹配字母“A”,后跟一个或多个数字。

Match.Email 模式比其他模式更复杂。 它可以检测并提取表单 local@hostname.tld中的常见电子邮件地址,可能来自长文本段落,并支持国际字符和表情符号。 使用它来验证将电子邮件地址作为输入的表单,作为快速测试输入是否在电子邮件表单中。 如果不提取,请使用 MatchOptions.Complete 检测 电子邮件地址,例如,在文本输入控件中。

但是, Match.Email 不会验证电子邮件地址是否符合电子邮件地址、域名和顶级域的许多不断发展的标准,这些标准需要一个复杂的正则表达式,需要不时更新。 Although 大多数电子邮件地址都按预期处理, Match.Email 匹配一些无效情况(例如主机名中的下划线),并且与一些有效情况(例如带引号的电子邮件地址或 IP 地址)不匹配。 如果需要,网络上有许多正则表达式用于检测真正合法的电子邮件地址。 在生产中使用之前,请务必根据您的特定需求测试正则表达式。

如果要查看使用的正则表达式,请评估公式 Text( Match.Email )。 第一部分匹配之前 @ 的字符,并根据 RFC 822 和 修订 版排除常见的 ASCII 标点符号以及 Unicode 开头和结束标点符号,以便于提取,例如 ([«和。 它不支持不常见且不鼓励使用带引号的字符串或注释。 在之后 @,正则表达式的第二部分和第三部分相同,并用 a . 分隔,确保地址中始终至少 . 有一个。 这些部分不包括除、和 .- 之外的所有 _ Unicode 标点符号。 不支持 IP 地址。 在整个电子邮件地址中,支持国际字符和表情符号。

在不 Power Apps使用 Power Fx 1.0 时, Match.EmailMatch.Hyphen 的定义略有不同。 Match.Email 更简单,但不适合提取电子邮件地址,因为它会捕获空格。 以前, Match.Hyphen 是在字符类之外转义的,现在是非法的。

编号子匹配项

使用 MatchOptions.NumberedSubMatches 启用 ,没有内联选项。 (?n) 支持与此选项相反的兼容性,并且是默认值。

默认情况下, (...) 不捕获,相当于大多数系统所说的“显式捕获”。要捕获,请使用带有反向引用 (?<name>...)\k<name>命名捕获。 使用命名捕获可以不捕获不需要的组,通过使用名称提高清晰度,并且在捕获位置发生变化时不易出错,从而提高性能。

如果您已有正则表达式,则可能取决于自动捕获和编号的组,包括编号的反向引用。 通过使用 MatchOptions.NumberedSubMatches 选项,可以使用此行为。

命名和编号的子匹配不能一起使用。 由于某些实现以不同的方式处理编号和命名捕获组的混合, Power Fx 因此不允许这样做。

可能是空的子匹配项

如引言所述, Power Fx的正则表达式有意仅限于可以在 .NET、JavaScript 和其他编程语言正则表达式引擎上一致实现的功能。 创作时错误会阻止使用不属于此集的功能。

实现之间可能不同的一个领域是如何处理空子匹配。 例如,考虑要求匹配文本 (?<submatch>a*)+ 的正则表达式 a。 在 .NET 上,子匹配会导致空文本字符串,而在 JavaScript 上,子 a匹配会导致空文本字符串。 两者都可以被认为是正确的实现,因为 + 量词可以用空字符串来满足,因为组的内容有一个 * 量词。

为避免实现之间的 Power Fx 结果不同,可能为空的子匹配项不能与量词一起使用。 以下是子匹配如何为空的示例:

示例 Description
(?<submatch>a{0,}b*)+ 子匹配的所有内容都是可选的,因此整个子匹配可能是空的。
((<submatch>a)?b)+ 由于子匹配项外部, ? 子匹配项整体是可选的。
(?<submatch>a|b*)+ Alternation 如果子匹配中的内容可能为空,可能会导致整个子匹配为空。
((?<submatch>a)|b)+ 子匹配项之外的 Alternation 可以匹配 b ,在这种情况下,子匹配项将为空。

中的 (?<submatch>a+)+ 子匹配不能为空,因为子匹配中必须至少有一个 a 子匹配,并且受支持。

Unicode

Power Fx 正则表达式使用 Unicode 类别来定义 \w\d\s并具有 \p{..}特定类别。

这些定义可能因平台而异。 例如,Unicode 标准会不时更新新字符,稍后将由平台按照自己的节奏实现。 在所有平台更新之前,预计不同平台的结果会有所不同。

Power Fx 正则表达式确保类别信息始终可用于基本多语言平面(字符 U+0 到 U+ffff)。 某些平台不会为补充多语言平面及以后的字符(U+10000 到 U+10ffff)实现类别。 此限制通常不是问题,因为基本多语言平面中的字符是最常用的。 如果方案涉及 U+10000 或超过 U+10000 的字符,请直接使用字符值而不是类别。 在您打算使用的平台上测试您的正则表达式。

平台之间可能存在微小的边缘情况差异。 例如,某些平台在调用 MatchOptions.IgnoreCase ſs 可能不会被视为 匹配 。 如果这些字符对方案很重要,请使用字符类 like [ſsS] 不区分大小写进行匹配,并显式包含所需的字符。