?? 东北麻将免费游戏大厅: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......  的输出顺序与 q1、q2......  一致。

2.  单个字符的匹配

我们先从简单的开始  ——  以 regexpi 函数为例,不区分字符的大小写。假设你要搜索  "cat",搜索用

的正则表达式就是  "cat",这与文本编辑工具里常用的 CTRL+F 是一样的,即正则表达式  "cat"  匹配  "cat"、

"Cat"、"cAt"、"CAt"、"caT"、"CaT"、"cAT"、"CAT"。

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

2.1  句点符号

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

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

Matlab 程序实例:

clear;clc

str="ten,&8yn2tin6ui>&ton, t n,-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 只匹配 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")    %í?ê±ê?3??eê?????oí×ó′?

o11 =          1        10        18

o22 =          3        12        20

o33 =        "ten"        "tin"        "ton"

2.3  方括号中的连接符

"[c1-c2]"  ——  匹配从字符 c1 开始到字符 c2 结束的字母序列(按字母表中的顺序)中的任意一个。 例如  [a-c]  匹配  a、b、c、A、B、C,即正则表达式  t[a-z]n  匹配  tan、tbn、tcn、tdn、ten、……、txn、tyn、tzn。

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 =          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 = "<tr valign=top><td><a name="19184"></a>xyz";

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

ans =        "<tr valign=top><td><a name="19184"></a>"

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

例如:

>>str = "<tr valign=top><td><a name="19184"></a>xyz";

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

ans =        "<tr valign=top>"        "<td>"        "<a name="19184">"        "</a>"

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

>>str = "<tr valign=top><td><a name="19184"></a>xyz";

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

ans =          {}

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

ans =        "<tr valign=top><td><a name="19184"></a>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"

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

>> regexpi(lstr, "\<s\w*", "match")

ans =        "such"        "stories"

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

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

ans =        "collection"

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

>>regexpi(lstr, "\<s\w*h\>", "match")

ans =        "such"

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

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

s="Grammar Of, relating to, or being a noun or pronoun case that indicates 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"

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

>>regexpi(s,"(?<!,\s*)\w*","match")

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 that indicates 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 语句中类似<a>abc</a>的部分:

hstr = "<!comment><tr nam="7507"></tr><table>Default</table><br>";

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

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

>> mat{:}

ans =                            <tr nam="7507"></tr>

ans =                            <table>Default</table>

>> 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

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

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

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

"suddenly there came a tapping,"];

>>regexp(poestr, "(?<nonwhitechar>\S)\k<nonwhitechar>", "match")

ans =          "dd"        "pp"        "dd"        "pp"

(?(tok)expr)  如果标记 tok 已经产生,则匹配表达式 expr。if-then 结构。其中的标记可以是数字标记,也可以是命名标记。 (?(tok)expr1|expr2)  如果标记 tok 已经产生,则匹配表达式 expr1,否则匹配表达式 expr2。if-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 woods these are I think I know."

8                                %                  |8

ans =                                  % "His house is in the village though;"

23                                %                                    |23

ans =                                  % "He will not see me stopping here"

6        14        23        %            |6        |14          |23

ans =                                  % "To watch his woods fill up with snow."

15        22                    %                            |15    |22

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

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

expr = {"i\s", "hou", "(.)\1", "\<w[aeiou]"};

idx = regexpi(cstr, expr);

idx{:}

ans =                                  % "Whose woods these are I think I know."

23        31                    %                                                |23          |31

ans =                                  % "His house is in the village though;"

5        30                    %          |5                                  |30

ans =                                  % "He will not see me stopping here"

6        14        23        %            |6        |14            |23

ans =                                  % "To watch his woods 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 I know."

"His house is in the vi--age though;"

"He wi-- not s-- me sto--ing here"

"To watch his w--ds fi-- 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:删掉<和/>和它们之间的部分,例如:

处理前:Hello <a href="world">world</a>. 2 < 5

处理后:Hello world. 2 < 5

ss="Hello <a href="world">world</a>. 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,"(?<!0)0{1,3}(?!0)", repmat("1", size("$0")));

a1=b1-48

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。

http://www.wquz.com.cn/style/images/nopic.gif
?
分享
评论
东北麻将玩法