构建模式表达式
自 R2020b 开始提供
模式是帮助搜索和修改文本的工具。与正则表达式类似,模式定义匹配文本的规则。模式可与文本搜索函数(如 contains
、matches
和 extract
)结合使用来指定这些函数作用于文本的哪些部分。您可以使用模式函数、运算符和字面文本,以类似于构建数学表达式的方式构建模式表达式。由于构建模式表达式是开放式的,因此模式可能变得相当复杂。分步构建模式并使用 maskedPattern
和 namedPattern
等函数有助于组织复杂的模式。
构建简单模式
最简单的模式是从单模式函数构建的。例如,lettersPattern
匹配任何字母字符。有许多模式函数用于匹配不同类型的字符和文本的其他特征。这些函数的列表可以在 pattern
参考页上找到。
txt = "abc123def";
pat = lettersPattern;
extract(txt,pat)
ans = 2x1 string
"abc"
"def"
模式通过使用 plus(+)
运算符与其他模式和字面文本相结合。此运算符按照在模式表达式中定义的顺序将模式和文本附加在一起。组合模式只匹配相同顺序的文本。在此示例中,“YYYY/MM/DD”不是匹配项,因为文本末尾必须有包含四个字母的字符串。
txt = "Dates can be expressed as MM/DD/YYYY, DD/MM/YYYY, or YYYY/MM/DD"; pat = lettersPattern(2) + "/" + lettersPattern(2) + "/" + lettersPattern(4); extract(txt,pat)
ans = 2x1 string
"MM/DD/YYYY"
"DD/MM/YYYY"
使用 or(|)
运算符指示两个指定模式中只要有一个模式匹配文本段即可。如果两个模式都无法匹配,则模式表达式的匹配失败。
txt = "123abc";
pat = lettersPattern|digitsPattern;
extract(txt,pat)
ans = 2x1 string
"123"
"abc"
一些模式函数将模式作为其输入,并以某种方式修改它们。例如,optionalPattern
会尽可能匹配指定的模式,但它并非成功匹配的必需条件。
txt = ["123abc" "abc"]; pat = optionalPattern(digitsPattern) + lettersPattern; extract(txt,pat)
ans = 1x2 string
"123abc" "abc"
边界模式
边界模式是一种特殊类型的模式,它不匹配字符,而是匹配指定字符类型和其他字符之间的边界,或匹配文本段的开头或结尾。例如,digitBoundary
匹配数字字符和非数字字符之间的边界,以及数字字符和文本的开头或结尾之间的边界。它不匹配数字字符本身。对于像 split
这样的函数,边界模式是有用的定界符。
txt = "123abc";
pat = digitBoundary;
split(txt,pat)
ans = 3x1 string
""
"123"
"abc"
边界模式是特殊模式,因为可以使用 not(~)
运算符对其求反。当以这种方式求反时,边界模式在不满足上述要求的字符之前或之后进行匹配。例如,~digitBoundary
匹配满足以下条件的两者之间的边界:
都是数字的两个字符
都是非数字的两个字符
一个非数字字符和一段文本的开头或末尾
使用 replace
用 "|"
字符标记 ~digitBoundary
匹配的位置。
txt = "123abc"; pat = ~digitBoundary; replace(txt,pat,"|")
ans = "1|2|3a|b|c|"
分步构建复杂模式
有时简单模式不足以解决问题,需要更复杂的模式。随着模式表达式的增加,理解它匹配什么内容会变得困难。简化构建复杂模式的一种方法是单独构建模式的每个部分,然后将这些部分组合成单一模式表达式。
例如,电子邮件地址使用 local_part@domain.TLD 形式。三个标识符(local_part、domain 和 TLD)都必须为数字、字母和下划线字符的组合。要构建完整模式,首先要为标识符定义模式。构建一个模式,用它匹配一个字母或数字字符或一个下划线字符。
identCharacters = alphanumericsPattern(1) | "_";
现在,使用 asManyOfPattern
来匹配 identCharacters
的一个或多个连续实例。
identifier = asManyOfPattern(identCharacters,1);
接下来,构建一个模式,用它匹配包含多个标识符的电子邮件地址。
emailPattern = identifier + "@" + identifier + "." + identifier;
通过查看该模式与以下示例电子邮件地址的匹配效果来测试模式。
exampleEmails = ["janedoe@mathworks.com" "abe.lincoln@whitehouse.gov" "alberteinstein@physics.university.edu"]; matches(exampleEmails,emailPattern)
ans = 3x1 logical array
1
0
0
尽管所有电子邮件地址都是有效的,但该模式还是无法匹配其中几个示例电子邮件地址。local_part 和 domain 都可以由一系列用句点分隔的标识符组成。使用 identifier
模式构建能够匹配一系列标识符的模式。asManyOfPattern
匹配尽可能多的指定模式的并发实例,但如果没有,模式的其余部分仍然能够成功匹配。
identifierSeries = asManyOfPattern(identifier + ".") + identifier;
使用此模式构建一个新 emailPattern
,它可以匹配所有示例电子邮件地址。
emailPattern = identifierSeries + "@" + identifierSeries + "." + identifier; matches(exampleEmails,emailPattern)
ans = 3x1 logical array
1
1
1
组织模式显示
复杂的模式有时很难阅读和解释,尤其是对于那些不熟悉模式结构的人来说。例如,emailPattern
在显示时就又长又难读。
emailPattern
emailPattern = pattern
Matching:
asManyOfPattern(asManyOfPattern(alphanumericsPattern(1) | "_",1) + ".") + asManyOfPattern(alphanumericsPattern(1) | "_",1) + "@" + asManyOfPattern(asManyOfPattern(alphanumericsPattern(1) | "_",1) + ".") + asManyOfPattern(alphanumericsPattern(1) | "_",1) + "." + asManyOfPattern(alphanumericsPattern(1) | "_",1)
显示难以阅读的问题部分在于存在许多重复的 identifier
模式。如果此模式的确切细节对模式的用户不重要,则可以使用 maskedPattern
隐藏 identifier
模式的显示。此函数创建一个新模式,其中 identifier
显示为掩码,而改为显示变量名称 "identifier"
。您也可以指定显示不同名称。通过在显示的模式中点击“Show all details
”,可以访问采用这种掩码方式的模式的详细信息。
identifier = maskedPattern(identifier);
identifierSeries = asManyOfPattern(identifier + ".") + identifier
identifierSeries = pattern
Matching:
asManyOfPattern(identifier + ".") + identifier
Use details to show more information
可以使用 namedPattern
函数进一步组织模式。namedPattern
将模式指定为某个命名模式,当与其他模式组合时,该模式会更改显示方式。电子邮件地址有几个重要部分,local_part@domain.TLD,每个部分都有自己的匹配规则。为每个部分创建一个命名模式。
localPart = namedPattern(identifierSeries,"local_part");
命名模式可以嵌套,以进一步描述模式的各个部分。要嵌套命名模式,请使用若干命名模式构建一个模式,然后将该模式指定为一个命名模式。例如,Domain.TLD 可分为域、子域和顶层域 (TLD)。为 domain.TLD 的每个部分创建命名模式。
subdomain = namedPattern(identifierSeries,"subdomain"); domainName = namedPattern(identifier,"domainName"); tld = namedPattern(identifier,"TLD");
将域的各组成部分的命名模式嵌套在另一个命名模式 domain
下。
domain = optionalPattern(subdomain + ".") + ... domainName + "." + ... tld; domain = namedPattern(domain);
将这些模式组合成一个命名模式 emailPattern
。在 emailPattern
的显示中,您可以看到每个命名模式及其匹配项,以及关于任何嵌套命名模式的信息。
emailPattern = localPart + "@" + domain
emailPattern = pattern
Matching:
local_part + "@" + domain
Using named patterns:
local_part : asManyOfPattern(identifier + ".") + identifier
domain : optionalPattern(subdomain + ".") + domainName + "." + TLD
subdomain : asManyOfPattern(identifier + ".") + identifier
domainName: identifier
TLD : identifier
Use details to show more information
您可以通过对模式进行点索引来访问命名模式和嵌套命名模式。例如,通过从 emailPattern
到 domain
的点索引然后到 subdomain
的点索引,可以访问嵌套的命名模式 subdomain
。
emailPattern.domain.subdomain
ans = pattern
Matching:
asManyOfPattern(identifier + ".") + identifier
Use details to show more information
点赋值可用于更改命名模式,而不需要重写模式表达式的其余部分。
emailPattern.domain = "mathworks.com"
emailPattern = pattern
Matching:
local_part + "@" + domain
Using named patterns:
local_part: asManyOfPattern(identifier + ".") + identifier
domain : "mathworks.com"
Use details to show more information
Copyright 2020 The MathWorks, Inc.
另请参阅
pattern
| string
| regexp
| contains
| replace
| extract