MATLAB正则表达式
责任编辑:icynet    浏览:977次    时间: 2015-06-02 21:57:28      

摘要:1. 引言 正则表达式就是一个表达式(也是一串字符),它定义了某种字符串模式——利用正则表达式,可以对大段的文字进行复杂的查找、替换等。本文将以 Matlab 为编程语言,讲解正则表达式的概念和使用方法,并将在文末以实例说明正则表达式的实践应用。 Matlab 提供..

关键词:MATLAB 正则 表达式
分享到:

1.  引言

正则表达式就是一个表达式(也是一串字符),它定义了某种字符串模式——利用正则表达式,可以对大段的文字进行复杂的查找、替换等。本文将以 Matlab 为编程语言,讲解正则表达式的概念和使用方法,并将在文末以实例说明正则表达式的实践应用。

Matlab 提供的正则表达式函数有三个:

regexp——用于对字符串进行查找,大小写敏感;

regexpi——用于对字符串进行查找,大小写不敏感;

regexprep——用于对字符串进行查找并替换。

简要介绍一下这三个函数,以 regexpi 为例  ——  读者可以先跳过这里,看过全文之后再来看这里。

用法 1

[start end extents match tokens names] = regexpi('str', 'expr')

start 为匹配字符串的起始位置;end 为匹配字符串的终止位置;extents 为扩展内容,和'tokens'指示符

一起用,指示出现 tokens 的位置;match 即找到的匹配字串;tokens 匹配正则表达式中标记(tokens)的字串;

names 为匹配到的命名标记的标记名。

用法 2

若不需要所有的输出,可以用下面的方式有选择的输出。

[v1 v2 ...] = regexpi('str', 'expr', 'q1', 'q2', ...)

'q1''q2' ...... 'start''end''tokens''tokensExtents''match''names'  之一,意义与前文相同。v1

v2......  的输出顺序与 q1q2......  一致。              

2.  单个字符的匹配

我们先从简单的开始  —— regexpi 函数为例,不区分字符的大小写。假设你要搜索 'cat',搜索用的正则表达式就是 'cat',这与文本编辑工具里常用的 CTRL+F 是一样的,即正则表达式 'cat'  匹配 'cat''Cat''cAt''CAt''caT''CaT''cAT''CAT'

为了方便,下面的叙述中字符串和正则表达式的''都省略不写。

2.1  句点符号    

.  ——  匹配任意一个(只有一个)字符(包括空格)。

假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以  't' 字母开头,以  'n' 字母结束;另外,有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符  —— 句点符号  '.' 。这样,完整的表达式就是 t.n,它匹配 tantentin ton,还匹配 t#ntpn 甚至 t n,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格,即:正则表达式 t.n 匹配 tentintont ntpnt#nt@n 等。

Matlab 程序实例:

clear;clc

str='ten,&8yn2tin6ui>&ton, tn,-356tpn,$$$$t#n,4@).,t@nT&nY';

pat='t.n';

o1=regexpi(str,pat,'start')             %'start'指定输出 o1 为匹配正则表达式的子串的起始位置

o2=regexpi(str,pat,'end')               %'end'指定输出 o2 为匹配正则表达式的子串的结束位置

o3=regexpi(str,pat,'match')           %'match'指定输出 o3 为匹配正则表达式的子串                        

[o11,o22,o33]=regexpi(str,pat,'start','end','match')           %同时输出起始位置和字串

输出为:

o22 =          3         8        13        18       23        28       33        36

o33 =        'ten'       'tin'        'ton'        't n'       'tpn'        't#n'       't@n'        'T&n'

o1 =          1       10        18        23       31        39       48        51

o2 =          3       12        20        25       33        41       50        53

o3 =        'ten'       'tin'        'ton'        't n'       'tpn'        't#n'       't@n'        'T&n'

o11 =          1       10        18        23       31        39       48        51

o22 =          3       12        20        25       33        41       50        53

o33 =        'ten'       'tin'        'ton'        't n'       'tpn'        't#n'       't@n'        'T&n'

2.2  方括号符号

[oum]  ——  匹配方括号中的任意一个。

为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号([])里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式 t[aeio]n 只匹配 tanTentin toN等。但 Tmntaen 不匹配,因为在方括号之内你只能匹配单个字符。

Matlab 程序实例:

clear;clc

str='ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY';

pat='t[aeiou]n';                    

[o11,o22,o33]=regexpi(str,pat,'start','end','match')   %í?ê±ê?3??eê?????oí×ó′?

o11 =          1       10        18

o22 =          3       12        20

o33 =        'ten'       'tin'        'ton'

2.3  方括号中的连接符

'[c1-c2]'  ——  匹配从字符 c1 开始到字符 c2 结束的字母序列(按字母表中的顺序)中的任意一个。 例如  [a-c]  匹配  abcABC,即正则表达式  t[a-z]n  匹配  tantbntcntdnten……txntyntzn

Matlab 程序实例:

clear;clc

str='ten,&8yn2tin6ui>&ton, tn,-356tpn,$$$$t#n,4@).,t@nT&nY';

pat='t[a-z]n';                      

[o11,o22,o33]=regexpi(str,pat,'start','end','match')  

o11 =          1       10        18        31

o22 =          3       12        20        33

o33 =          'ten'       'tin'        'ton'       'tpn'

2.4  特殊字符

\.  —— 即由  '\' 引导的,代表有特殊意义或不能直接输入的单个字符。

在使用 fprintf 函数输出时我们常用  '\n'  来代替回车符,这里也是同样的道理,用  \n 在正则表达式中表示回车符。类似的还有  \t 横向制表符,'\*'  表示  '*'  等。后一种情况用在查询在正则表达式中有语法作用的字符,详见下文。

下面是一些匹配单个字符的转义字符正则表达式及所匹配的值。

\xN \x{N}  匹配八进制数值为 N 的字符

\oN \o{N}  匹配十六进制数值为 N 的字符

\a                    Alarm(beep)

\b                    Backspace

\t                     水平 Tab

\n                    New line

\v                    垂直 Tab

\f                    换页符

\r                    回车符

\e                    Escape

\c     某些在正则表达式中有语法功能或特殊意义的字符 c,要用  \c  来匹配,而不能直接用  c 匹配,例如  . 用正则表达式  \. 匹配,而  \ 用正则表达式  \\ 匹配。

Matlab 程序实例:

clear;clc

str='l.[a-c]i.$.a';

pat1='.';pat2='\.';

o=regexpi(str,pat1,'match')

o1=regexpi(str,pat2,'match')

输出为:

o =        'l'       '.'        '['        'a'       '-'        'c'       ']'        'i'        '.'       '$'        '.'       'a'

o1 =        '.'       '.'        '.'

2.5  类表达式

\w\s    \d  ——  匹配某一类字符中的一个。

和上面的  \n 等表中的转义字符有所不同,\w\s\d  等匹配的不是某个特定的字符,而是某一类字符。具体说明如下:

\w            匹配任意的单个文字字符,相当于 [a-zA-Z0-9_]

\s             匹配任意的单个空白字符,相当于 [\t\f\n\r]

\d             匹配任意单个数字,相当于 [0-9]

\S            匹配除空白符以外的任意单个字符,相当于 [^\t\f\n\r]  ——  方括号中的^表示取反;

\W           匹配任意单个字符,相当于 [^a-zA-Z0-9_]

\D            匹配除数字字符外的任意单个字符,相当于 [^0-9]

Matlab 程序实例:

s='This city has a population of more than 1,000,000.';

ptn='\d';

regexp(s,ptn,'match')

输出为:

ans =          '1'       '0'        '0'        '0'       '0'        '0'       '0'

3.字符串的匹配

3.1  多次匹配

例如需要匹配 'ppp',那么就可以用正则表达式 'ppp',还有一种更简单一点的记法 'p{3}'。正则表达式中的  '{}' 用来表示匹配前面的表达式的出现次数,即 'p{2,3}'  匹配  'pp' 'ppp'。除了  '{}',还有几个

字符,用在表示单个字符的正则表达式后面表示次数,如下所述:

expr?   expr 匹配的元素出现 0 1 次,相当于{0,1}

expr*   expr 匹配的元素出现 0 次或更多,相当于{0,}

expr+   expr 匹配的元素出现 1 次或更多,相当于{1,}

expr{n}   expr 匹配的元素出现 n 次,相当于{n,n}

expr{n,}   expr 匹配的元素至少出现 n

expr{n,m}   expr 匹配的元素出现 n 次但不多于 m

假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式为 [0-9]{3}\-[0-9]{2}\-[0-9]{4}。在正则表达式中,连字符(“-”)有着特殊的意义,因此,它的前面要加上一个转义字符  \

如果希望连字符号可以出现,也可以不出现  —— 999-99-9999 999999999 都属于正确的格式。这时,你可以在连字符号后面加上  '?' 数量限定符。这样正则表达式为 [0-9]{3}\-?[0-9]{2}\-?[0-9]{4} 另外,当我们使用 expr*  时,Matlab 将尽可能的匹配最长的字符子串。如:

>>str = '

'        'Default

xyz';

>>regexp(hstr, '<.*>', 'match')

ans =        '

'

如果我们希望匹配尽可能短的字符子串时,可以在上面我们使用的字符串后使用  '?',也就是 expr*?

例如:

>>str = '

xyz';

>>regexp(hstr, '<.*?>', 'match')

ans =        '

'        ''        ''

这个表达式的执行过程是这样的,先执行 expr*,“游标(如果有的话)就指到了与 expr*  匹配的字符子串的最末端,然后从那里开始再检查下一个字符与后面的表达式是否匹配,如果匹配就继续向前(如果一直成功则返回最长的字符串),如果不匹配则直接返回空。例如:

>>str = '

xyz';

>>regexp(hstr, '<.*+>', 'match')

ans =          {}

>>regexp(hstr, '<.*+', 'match')

ans =        '

xyz'

3.2    逻辑运算符

exp|exp2  表示或者满足 exp 或者满足 exp2

(expr)   expr 标记为一组,匹配 expr,并将匹配的字符子串标记起来以供后面使用。关于这部分内容下面还会有更详细介绍。

(?:expr)  表示 expr 为一组,相当于数学表达式中的()

例如:

lstr='A body or collection of such stories';

regexp(lstr,'(?:[^aeiou][aeiou]){2,}','match')

ans =        'tori'

上面的表达式中  {2,} [^aeiou][aeiou]  起作用,如果去掉分组,则只对 [aeiou]  起作用,如下所示:

>>regexp(lstr,'[^aeiou][aeiou]{2,}','match')

ans =        'tio'       'rie'

(?>expr) expr 中的每个元素是一个分组。(?#expr) 放在(?#)之间的是注释。如:

>>regexp(lstr, '(?# Match words in caps)[A-Z]\w*','match')

ans =        'A'

expr1|expr2  匹配 expr1 或者 expr2 两者之一即可。

>>regexp(lstr, '[^aeiou\s]o|[^aeiou\s]i', 'match')

ans =        'bo'       'co'        'ti'        'to'       'ri'

^expr  匹配 expr,并且出现在原字符串最前端的子串。expr$ 匹配 expr,并且出现在原字符串最末端的子串。

>>pi(lstr, '^a\w*|\w*s$', 'match')

ans =        'A'       'stories'

\

>> regexpi(lstr, '\

ans =        'such'       'stories'

expr\>  匹配 expr,并且出现在一个单词最末端的子串。

>> regexpi(lstr, '\w*tion\>', 'match')

ans =        'collection'

\  更严格的单词匹配,如:以 s 开头,并且以 h 结尾的单词。

>>regexpi(lstr, '\', 'match')

ans =        'such'

3.3  左顾右盼  —— 利用上下文匹配

利用上下文的匹配来找到我们要找的内容。expr1(?=expr2) 找到匹配 expr1 的子串,如果其后的字符串也匹配 expr2。如下面的例子查找所有在','之前的单词。

s='Grammar Of, relating to, or being a noun or pronoun case thatindicates possession.';

ptn='\w*(?=,)';

regexp(s,ptn,'match')

ans =        'Of'       'to'

expr1(?!expr2)  找到匹配 expr1 的子串如果其后的字符串不匹配 expr2。下面的例子匹配所有不在','之前的单词:

>>regexpi(s, '\w*(?!=,)', 'match')

ans =          'Grammar'       'Of'        'relating'       'to'        'or'        'being'       'a'        'noun'       'or'    

'pronoun'        'case'       'that'        'indicates'       'possession'

(?<=expr1)expr2  找到匹配 expr2 的子串,如果其前面的字符串也匹配 expr1。下面的例子查找所有在  ','之后的单词,注意  ','  之后可能有空格。

>>regexpi(s,'(?<=,\s*)\w*','match')

ans =          'relating'       'or'

(?

>>regexpi(s,'(?

ans =       'Grammar'       'Of'        'elating'        'to'       'r'        'being'       'a'        'noun'       'or'

      'pronoun'       'case'        'that'       'indicates'        'possession'

4.标记(tokens)

这部分是比较难的一部分,但是应用得当可以实现非常强大的功能。

4.1  什么是标记(tokens)

任何的正则表达式都可以用圆括号括起来作为一个标记。例如,创建一个记录钱数的标记,就可以用($\d+)。这样与之匹配的字符串就会被记录下来,根据这个标记出现的顺序,可以使用  \n 来引用匹配这个标记的字符串。如  \3 来引用与标记相匹配的第三个字符串。(如果在替换函数 regexprep 中,需要用  $3

来引用。) 下面是一个例子,\S 查找任意的非空白字符,\1 用来说明要匹配第一个tokens的内容,也就是要立即再次查找刚刚匹配到的同一个字符,并且要紧挨着第一个。'tokens' 选项用来向 tok 输出所有匹配到的标记;而 'tokenExtents'  则用来表示匹配标记的起始位置。

s='Grammar Of, relating to, or being a noun or pronoun case thatindicates possession.';

[mat,tok,ext]=regexpi(s, '(\S)\1','match','tokens','tokenExtents')

>>mat

mat =          'mm'       'ss'        'ss'

>>tok{:}

ans =          'm'

ans =          's'

ans =          's'

>>ext{:}

ans =          4         4

ans =        75       75

ans =        78       78

4.2  如何使用标记?

(expr)  记录所有匹配表达式的字符,并做为一个标记,以备后面使用。如上面的例子,利用标记实现查找连续的重复字母。

\N  匹配同一条正则表达式里的第 N  个标记中的字符串,例如  \1 匹配第一个标记。下面的例子可以查找 html 语句中类似abc的部分:

      hstr = '

';

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

      [mat tok] = regexp(hstr, expr,'match', 'tokens');

>> mat{:}

ans =                          

ans =                           Default

>> tok{:}

ans =                                   'tr'

ans =                                   'table'

$N  在一个替换字符串中插入与第 N 个标记相匹配的字符串(只用于 regexprep 函数)。下面的例子可以将匹配到的第一个 token 和第二个 token 的位置互换:

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

ans =                       Baker, Norma Jean

(?expr)  记录所有匹配表达式 expr 的字符,做为一个标记,并设定一个名字 name\k      

与名为 name 的标记相匹配。下面这个例子和这部分第一个例子是一样的,只不过使用了命名的标记。

>>poestr = ['While I nodded, nearly napping, ' ...

                         'suddenly there came a tapping,'];

      >>regexp(poestr, '(?\S)\k','match')

ans =          'dd'       'pp'        'dd'       'pp'

(?(tok)expr)  如果标记 tok 已经产生,则匹配表达式 exprif-then 结构。其中的标记可以是数字标记,也可以是命名标记。(?(tok)expr1|expr2)  如果标记 tok 已经产生,则匹配表达式 expr1,否则匹配表达式 expr2if-then-else结构下面的例子用来检查一个句子中的性别用词是否匹配,表达式的意思就是,如果前面用的是 'Mrs'  

么后面就匹配 'her',如果前面用的是'Mr',也就是没有匹配到  'Mr'  后面的  's',则后面匹配  'his'

>>expr = 'Mr(s?)\..*?(?(1)her|his) son';

>>[mat tok] = regexp('Mr. Clark went to see his son',expr, 'match', 'tokens')

      mat =             'Mr. Clark went to see his son'

tok =            {1x2 cell}

>>tok{:}

ans =                                     ''       'his'

如果把句子中的 his 改成 her,则没有与之匹配的结果。

>>[mat tok] = regexp('Mr. Clark went to see her son',expr, 'match', 'tokens')

mat =                                     {}

tok =                                     {}

5.多行字符串与多正则表达式

5.1  多字符串与单个正则表达式匹配

多个字符串存在一个元胞数组里之后,每一个字符串与正则表达式匹配,返回值的维数与元胞数组相同。

cstr = {                                                                 ...

'Whose woods these are I think I know.' ; ...

'His house is in the village though;'      ; ...

'He will not see me stopping here'           ; ...

'To watch his woods fill up with snow.'};

>>idx{:}

ans =                                 % 'Whose woodsthese are I think I know.'

      8                               %                 |8

ans =                                 % 'His house isin the village though;'

    23                               %                                  |23

ans =                                 % 'He will notsee me stopping here'

      6        14       23        %           |6        |14         |23

ans =                                 % 'To watch hiswoods fill up with snow.'

    15        22                   %                          |15    |22

5.2  多个字符串与多个正则表达式匹配

这种情况下,应该满足字符串元胞数组中字符串的个数和正则表达式的个数相等——但维数不一定要相等——如可以用 4*1 的元胞数组与 1*4 的正则表达式相匹配。

expr = {'i\s', 'hou', '(.)\1', '\

idx = regexpi(cstr, expr);

idx{:}

ans =                                 % 'Whose woodsthese are I think I know.'

    23        31                   %                                              |23         |31

ans =                                 % 'His house isin the village though;'

      5        30                   %         |5                                 |30

ans =                                 % 'He will notsee me stopping here'

      6        14       23        %           |6        |14           |23

ans =                                 % 'To watch hiswoods fill up with snow.'

              4       14        28       %        |4             |14                  |28

5.3  多字符串的替换

这个功能是在匹配的基础上,在正则表达式后面加入要替换的字符串即可。下面这个是 matlab 中的例子,很容易理解。

>>s = regexprep(cstr, '(.)\1', '--', 'ignorecase')

s =        'Whose w--ds these are I think Iknow.'

          'His house is in thevi--age though;'

          'He wi-- not s-- mesto--ing here'

          'To watch his w--dsfi-- up with snow.

6.应用实例

问题 1:查找包含某个字串的串。例如:

str =  {'apple_food'  ,  'chocolates_food', 'ipod_electronics',  'dvd_player_electronics', 'water_melon_food'}

中查找字串'food',得到结果  [1 1 0 0 1]

str = {'apple_food' , 'chocolates_food', 'ipod_electronics','dvd_player_electronics', 'water_melon_food'} ;

ptn='food';

m1=regexp(str,ptn,'match');

ix=~cellfun('isempty',m1);

问题 2:如何将 Matlab 中的  ^  转换成 C 语言?如将 a^b 转换成 a**b,或者 pow(a,b)。以下式为例:

s=1/2*w/(1+Pf^2*Pc-Pf^2*Pc*w1-w1*Pf^2-Pf*Pc-Pf^2*w^2+2*w1*Pf-2*Pf)

Matlab 提供了 ccode 命令,用于将 Matlab 转换为 c,这里仅为一例:

s='1/2*w/(1+Pf^2*Pc-Pf^2*Pc*w1-w1*Pf^2-Pf*Pc-Pf^2*w^2+2*w1*Pf-2*Pf)';

ptn='(\w{1,2})\^(\d{1})';

regexp(s,ptn,'tokens');

s1=regexprep(s,ptn,['pow(','$1',',','$2',')'])

问题 3:删掉</>和它们之间的部分,例如:

处理前:Helloworld. 2 < 5

处理后:Helloworld. 2 < 5

ss='Hello world. 2 < 5';

b='<.*?>';

sr=regexprep(ss,b,'')

问题 4:游程平滑算法:将连续的且个数小于某个阈值的 0 全部替换成 1,例如:

平滑前:1111100000111100011

平滑后:1111100000111111111

a = [1 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 00 0 0 0 1 1 1 1 1 1];

T = 4;

b = sprintf('%d',a);

b1 = regexprep(b,'(?

a1=b1-48


】【打印繁体】【投稿】 【收藏】 【推荐】 【举报】 【评论】 【关闭】【返回顶部
发表评论
帐  号: 密码: (新用户注册)
验 证 码:
表 情:
内  容:
发表评论
用户评价(0)

暂时还没有任何评论

此文件不可写: