(转)Matlab 正则表达式regexp 以及用Matlab实现字符串分割(split)
(2014-07-08 10:08:50)分类: 结构设计 |
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' ......
v2......
2.
我们先从简单的开始
的正则表达式就是
'Cat'、'cAt'、'CAt'、'caT'、'CaT'、'cAT'、'CAT'。
为了方便,下面的叙述中字符串和正则表达式的''都省略不写。
2.1
.
假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以
Matlab 程序实例:
clear;clc
str='ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY';
pat='t.n';
o1=regexpi(str,pat,'start')
o2=regexpi(str,pat,'end')
o3=regexpi(str,pat,'match')
[o11,o22,o33]=regexpi(str,pat,'start','end','match')
输出为:
o22
=
o33
=
o1
=
o2
=
o3
=
o11
=
o22
=
o33
=
2.2
[oum]
为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号([])里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式 t[aeio]n 只匹配 tan、Ten、tin 和 toN等。但 Tmn、taen 不匹配,因为在方括号之内你只能匹配单个字符。
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')
o11
=
o22
=
o33
=
2.3
'[c1-c2]'
Matlab 程序实例:
clear;clc
str='ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY';
pat='t[a-z]n';
[o11,o22,o33]=regexpi(str,pat,'start','end','match')
o11
=
o22
=
o33
=
2.4
\.等
在使用 fprintf 函数输出时我们常用
下面是一些匹配单个字符的转义字符正则表达式及所匹配的值。
\xN 或\x{N}
\oN 或\o{N}
\a
\b
\t
\n
\v
\f
\r
\e
\c
Matlab 程序实例:
clear;clc
str='l.[a-c]i.$.a';
pat1='.';pat2='\.';
o=regexpi(str,pat1,'match')
o1=regexpi(str,pat2,'match')
输出为:
o
=
o1
=
2.5
\w、\s
和上面的
\w
\s
\d
\S
\W
\D
Matlab 程序实例:
s='This city has a population of more than 1,000,000.';
ptn='\d';
regexp(s,ptn,'match')
输出为:
ans
=
3.字符串的匹配
3.1
例如需要匹配
字符,用在表示单个字符的正则表达式后面表示次数,如下所述:
expr?
expr*
expr+
expr{n}
expr{n,}
expr{n,m}
假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是
999-99-9999。用来匹配它的正则表达式为
如果希望连字符号可以出现,也可以不出现
>>str = '
'xyz';
>>regexp(hstr, '<.*>', 'match') ans
= |
'
如果我们希望匹配尽可能短的字符子串时,可以在上面我们使用的字符串后使用 例如: >>str = ' |
xyz';
>>regexp(hstr, '<.*?>', 'match') ans
= |
' 这个表达式的执行过程是这样的,先执行 expr*,“游标”(如果有的话)就指到了与 >>str = ' |
xyz';
>>regexp(hstr, '<.*+>', 'match') ans
= >>regexp(hstr, '<.*+', 'match') ans
= |
xyz'
3.2 exp|exp2 (expr) (?:expr) 例如: lstr='A body or collection of such stories'; regexp(lstr,'(?:[^aeiou][aeiou]){2,}','match') ans
= 上面的表达式中 >>regexp(lstr,'[^aeiou][aeiou]{2,}','match') ans
= (?>expr) expr 中的每个元素是一个分组。(?#expr) >>regexp(lstr, '(?# Match words in caps)[A-Z]\w*', 'match') ans
= expr1|expr2 >>regexp(lstr, '[^aeiou\s]o|[^aeiou\s]i', 'match') ans
= ^expr >>pi(lstr, '^a\w*|\w*s$', 'match') ans
= \ >> regexpi(lstr, '\ ans
= expr\> >> regexpi(lstr, '\w*tion\>', 'match') ans
= \ >>regexpi(lstr, '\ ans
= 3.3 利用上下文的匹配来找到我们要找的内容。expr1(?=expr2) s='Grammar Of, relating to, or being a noun or pronoun case that indicates possession.'; ptn='\w*(?=,)'; regexp(s,ptn,'match') ans
= expr1(?!expr2) >>regexpi(s, '\w*(?!=,)', 'match') ans
= (?<=expr1)expr2 >>regexpi(s,'(?<=,\s*)\w*','match') ans
= (? >>regexpi(s,'(? ans
=
4.标记(tokens) 这部分是比较难的一部分,但是应用得当可以实现非常强大的功能。 4.1
任何的正则表达式都可以用圆括号括起来作为一个标记。例如,创建一个记录钱数的标记,就可以用($\d+)。这样与之匹配的字符串就会被记录下来,根据这个标记出现的顺序,可以使用 来引用。) 下面是一个例子,\S 查找任意的非空白字符,\1 用来说明要匹配第一个 tokens
的内容,也就是要立即再次查找刚刚匹配到的同一个字符,并且要紧挨着第一个。'tokens' s='Grammar Of, relating to, or being a noun or pronoun case that indicates possession.'; [mat,tok,ext]=regexpi(s, '(\S)\1','match','tokens','tokenExtents') >>mat >>tok{:} ans
= ans
= ans
= >>ext{:} ans
= ans
= ans
= 4.2 (expr) \N
|
';
>> mat{:}
ans
=
ans
=
>> tok{:}
ans
=
ans
=
$N
>> regexprep('Norma Jean Baker', '(\w+\s\w+)\s(\w+)', '$2, $1')
ans
=
(?expr)
与名为 name 的标记相匹配。下面这个例子和这部分第一个例子是一样的,只不过使用了命名的标记。
>>poestr = ['While I nodded, nearly napping, ' ...
ans
=
(?(tok)expr)
么后面就匹配
>>expr = 'Mr(s?)\..*?(?(1)her|his) son';
>>[mat tok] = regexp('Mr. Clark went to see his son', expr, 'match', 'tokens')
tok
=
>>tok{:}
ans
=
如果把句子中的 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
=
ans
=
ans
=
ans
=
5.2
这种情况下,应该满足字符串元胞数组中字符串的个数和正则表达式的个数相等——但维数不一定要相等——如可以用 4*1 的元胞数组与 1*4 的正则表达式相匹配。
expr = {'i\s', 'hou', '(.)\1', '\
idx = regexpi(cstr, expr);
idx{:}
ans
=
ans
=
ans
=
ans
=
5.3
这个功能是在匹配的基础上,在正则表达式后面加入要替换的字符串即可。下面这个是 matlab 中的例子,很容易理解。
>>s = regexprep(cstr, '(.)\1', '--', 'ignorecase')
s
=
6.应用实例
问题 1:查找包含某个字串的串。例如:
在 str
中查找字串'food',得到结果
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 中的
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:删掉<和/>和它们之间的部分,例如:
处理前:Hello world. 2 <
5
处理后:Hello world. 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 0 0 0 0 0 1 1 1 1 1 1];
T = 4;
b = sprintf('%d',a);
b1 = regexprep(b,'(?
a1=b1-48
用Matlab实现字符串分割(split)
matlab正则表达式任务c#oo用Matlab实现字符串分割(split)
Matlab的字符串处理没有C#强大,本身又没有提供OO特性,需要依赖别的手段完成这项任务。
我们在这里借助正则表达式函数regexp的split模式。一般语法:
S = regexp(str, char, 'split')
其中str是待分割的字符串,char是作为分隔符的字符(可以使用正则表达式)。分割出的结果存在S中。
以下面这样一串字符为例
Hello Nocturne Studio
首先去除首尾的多余空格:
str = deblank(str)
例1:设这几个字符串是以制表符分隔的,可以这样来做:
S = regexp(str, '\t', 'split')
例2:设这些字符串是以一个或多个空格分隔的,可以用正则表达式来描述:
S = regexp(str, '\s+', 'split')
这样,S(1)=’Hello’,S(2)=’Nocturne’,S(3)=’Studio’。
注意,上面得到的结果S是一个cell型变量,它的每个元素比如S(1)仍然是cell型的,只能用来display,不能直接用来进行字符串操作(比如获取其中的某个字符),所以我们在使用需要执行一次:
s1 = char(S(1))
这样的s1才是一个真正的字符串,可以进行后续的操作。