Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

正则表达式中的标文

简介

正则表达式中使用的括号不仅将该表达式的元素分组在一起,而且会为找到的与该组条件匹配的任何匹配项指定标文。您可以使用标文匹配同一文本的其他部分。使用标文的一个好处是,标文会记住所匹配的内容,因此您可以在搜索或替换过程中重新调用和重用匹配的文本。

表达式中的每个标文都被分配一个数字,从 1 开始,从左至右顺序递增。要在表达式的后面引用某个标文,请使用反斜杠并后跟标文编号进行引用。例如,引用表达式中第三组括号生成的标文时,请使用 \3

举一个简单的例子,如果您要搜索字符数组中相同顺序的字母,可以捕获第一个字母作为标文,然后搜索紧随其后的匹配字符。在以下所示的表达式中,只要 regexp 与字符数组中的任何非空白字符匹配,(\S) 短语就会创建一个标文。表达式的第二部分 '\1' 查找同一字符第一个实例后面紧跟的第二个实例。

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

[mat,tok,ext] = regexp(poe, '(\S)\1', 'match', ...
               'tokens', 'tokenExtents');
mat
mat =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

元胞数组 tok 包含多个元胞数组,其中每个元胞数组都包含一个标文。

tok{:}
ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}


ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}

元胞数组 ext 包含多个数值数组,其中每个数值数组都包含一个标文的开始索引和结束索引。

ext{:}
ans =

    11    11


ans =

    26    26


ans =

    35    35


ans =

    57    57

另一个示例捕获匹配的 HTML 标记对组(例如 <a></a>)以及这些标记之间的文本。用于此示例的表达式为

expr = '<(\w+).*?>.*?</\1>';

该表达式的第一部分 '<(\w+)' 匹配左尖括号 (<),后跟一个或多个字母、数字或下划线字符。封闭的圆括号捕获左尖括号后面的标文字符。

该表达式的第二部分 '.*?>.*?' 匹配此 HTML 标记的其余部分(一直到 > 的字符),以及可能位于下一个左尖括号之前的任何字符。

最后一部分 '</\1>' 匹配结尾的 HTML 标记中的所有字符。此标记由 </tag> 序列组成,其中 tag 表示捕获为标文的任何字符。

hstr = '<!comment><a name="752507"></a><b>Default</b><br>';
expr = '<(\w+).*?>.*?</\1>';

[mat,tok] = regexp(hstr, expr, 'match', 'tokens');
mat{:}
ans =

    '<a name="752507"></a>'


ans =

    '<b>Default</b>'
tok{:}
ans =

  1×1 cell array

    {'a'}


ans =

  1×1 cell array

    {'b'}

多个标文

下面是一个如何为标文分配值的示例。假定您要搜索以下文本:

andy ted bob jim andrew andy ted mark

您选择使用以下搜索模式来搜索上述文本:

and(y|rew)|(t)e(d)

此模式包含三个生成标文的带括号表达式。当您最后执行搜索时,系统将为每个匹配项生成以下标文。

匹配项

标文 1

标文 2

andy

y

 

ted

t

d

andrew

rew

 

andy

y

 

ted

t

d

只会使用最高级别的括号。例如,如果搜索模式 and(y|rew) 找到文本 andrew,则会为标记 1 分配值 rew。但是,如果使用搜索模式 (and(y|rew)),则会为标记 1 分配值 andrew

不匹配的标文

对于正则表达式中指定的标文,如果在待查文本中没有匹配项,regexpregexpi 会返回一个空字符向量 ('') 作为标文输出,同时还会返回一个范围,用来标记标文在字符串中预期出现的位置。

此处所示的示例会对一个字符向量执行 regexp,该字符向量指定了从 MATLAB® tempdir 函数返回的路径。正则表达式 expr 包括六个标文设定符,每个设定符代表路径的一部分。第三个设定符 [a-z]+ 在字符向量中没有匹配项,因为此部分的路径 Profiles 是以大写字母开头的:

chr = tempdir
chr =

    'C:\WINNT\Profiles\bpascal\LOCALS~1\Temp\'
expr = ['([A-Z]:)\\(WINNT)\\([a-z]+)?.*\\' ...
        '([a-z]+)\\([A-Z]+~\d)\\(Temp)\\'];

[tok, ext] = regexp(chr, expr, 'tokens', 'tokenExtents');

如果在文本中未找到标文,regexp 会返回一个空字符向量 ('') 作为标文以及一个包含标文范围的数值数组。而范围的第一个数字为字符串索引,用于标记标文预期出现的位置;范围的第二个数字为第一个数字减 1。

在此示例中,表达式中指定的第三个标文为空标文,因此返回的第三个标文为空:

tok{:}
ans =

  1×6 cell array

    {'C:'}    {'WINNT'}    {0×0 char}    {'bpascal'}    {'LOCALS~1'}    {'Temp'}

变量 ext 中返回的第三个标文范围的起始索引设置为 10,这是不含匹配项的词 Profiles 在路径中的起始位置。范围结束索引设置为起始索引减 1,也就是 9:

ext{:}
ans =

     1     2
     4     8
    10     9
    19    25
    27    34
    36    39

替代文本中的标文

在替代文本中使用标文时,请使用 $1$2 等符号,而不要使用 \1\2 等符号来引用标文。此示例捕获两个标文并颠倒它们的顺序。第一个标文 $1'Norma Jean',第二个标文 $2'Baker'。请注意,regexprep 返回修改后的文本,而不是起始索引的向量。

regexprep('Norma Jean Baker', '(\w+\s\w+)\s(\w+)', '$2, $1')
ans =

    'Baker, Norma Jean'

命名捕获

如果您在表达式中使用许多标文,则为这些标文分配名称可能会很有帮助,而不必跟踪为哪个标文分配了哪个标文编号。

引用表达式中的命名标文时,请使用语法 \k<name>,而不要使用 \1\2 等数字:

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

regexp(poe, '(?<anychar>.)\k<anychar>', 'match')
ans =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

命名标文还有助于标记 MATLAB 正则表达式函数的输出。当您处理许多文本段时尤其如此。

例如,从多个字符向量中解析街道地址的不同部分。为表达式中的每个标文分配了一个短名称:

chr1 = '134 Main Street, Boulder, CO, 14923';
chr2 = '26 Walnut Road, Topeka, KA, 25384';
chr3 = '847 Industrial Drive, Elizabeth, NJ, 73548';

p1 = '(?<adrs>\d+\s\S+\s(Road|Street|Avenue|Drive))';
p2 = '(?<city>[A-Z][a-z]+)';
p3 = '(?<state>[A-Z]{2})';
p4 = '(?<zip>\d{5})';

expr = [p1 ', ' p2 ', ' p3 ', ' p4];

正如以下结果所展示的,您可以通过命名标文使输出更易于使用:

loc1 = regexp(chr1, expr, 'names')
loc1 = 

  struct with fields:

     adrs: '134 Main Street'
     city: 'Boulder'
    state: 'CO'
      zip: '14923'
loc2 = regexp(chr2, expr, 'names')
loc2 = 

  struct with fields:

     adrs: '26 Walnut Road'
     city: 'Topeka'
    state: 'KA'
      zip: '25384'
loc3 = regexp(chr3, expr, 'names')
loc3 = 

  struct with fields:

     adrs: '847 Industrial Drive'
     city: 'Elizabeth'
    state: 'NJ'
      zip: '73548'

另请参阅

| |

相关主题