![MATLAB R2020a从入门到精通(升级版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/74/38507074/b_38507074.jpg)
7.6 利用正则表达式进行搜索
利用标准字符串函数(如findstr()),就可以在一个字符串中查找指定的字符序列,以及替换这些字符序列。但用户有时需要进行特殊的查找,如查找重复的字符、查找所有的大写字母、查找以大写字母拼写的单词,或者查找所有的以美元表示的金额(即以美元符号开头,后面是含有小数点的十进制数)等。
在进行字符串查找时,MATLAB 支持具有强大功能的正则表达式(Regular Expression)。正则表达式是指在某种查找模式下进行字符串匹配所使用的公式。正则表达式在UNIX系统中得到了广泛应用,如grep、awk、sed、vi等工具函数。
另外,熟悉Perl或其他编程语言的用户也会或多或少地用到正则表达式。在MATLAB中,实现正则表达式的方法很容易理解,并且具有许多特性,包括扩展正则表达式(Extended Regular Expression)。
如果读者对正则表达式的概念不是十分了解,则可以由浅入深,先从其简单的特性开始使用,然后使用更复杂的特性。
为了使读者循序渐进地了解正则表达式的概念,下面先介绍几个使用正则表达式的简单规则。可以创建一个字符串公式(又称为表达式),用来描述标识字符串匹配部分的准则。该表达式由一系列字符和可选的修正符组成,修正符通常用于定义子字符串匹配的准则。
最简单的字符串表达式是一个完全由文字符号组成的字符串,如下所示:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_60.jpg?sign=1739552410-5en8fITWi7QUDIq7q8N30KMk1o6Q6x9M-0-220a848d6285f666f3010472fa2b5b34)
上例在str中找到了4处'pe',分别位于Piper、peck和peppers中(其中peppers中含有两个'pe')。
也可以使用字符类来匹配指定类型的字符,如一个字母、一个数字或一个空格符,还可以用来匹配一个指定的字符集。最有用的字符类是一个句点(.),用来表示任意的单个字符。
另外一个有用的字符类是位于方括号([])中的字符序列或某一部分字符,这个语法通常用来表示寻找与方括号中任意一个字符元素匹配的字符串子集。
例如,在str中寻找第一个字符为p,并且最后一个字符为r或c的包含3个字符的组合,可以使用如下所示的代码:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_61.jpg?sign=1739552410-kO5PxmXerZcGEpxDEeWuN42vDK0y16Pq-0-c11a7fb2b594400978e9b964ed266102)
还可以使用如下所示的代码寻找str中所有的大写字母:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_62.jpg?sign=1739552410-vLtKABGwvHG6wNi0X06cL6ZQQrU94HGY-0-631bd0211afb954060ebbcef09ba8f62)
查找单个字符的字符串表达式如表7-6所示。
表7-6 查找单个字符的字符串表达式
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_63.jpg?sign=1739552410-aTS22L2wRbq9VLBTlTzs5hUX41anpZHW-0-49b81a6224c609ff4951ad778916556e)
表7-6中的字符串表达式可以使用正则表达式修正符或数量词进行修改。例如,如下所示的代码用于在str中查找所有的单词,其中使用了修正符“+”:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_64.jpg?sign=1739552410-VUazNxwsFGCcEWuRO3MODTsoBx4Bz6f1-0-fd8ad8e4098dfa8e60e238e25b23c386)
由此可以看出,修正符使字符串表达式的含义发生了变化:不包含修正符“+”的表达式表示查找所有的单个文字字符,而包含修正符“+”的表达式表示查找所有的单词,即由一个或多个文字字符组成的字符组合。
如下所示的代码用于在str中查找由两个p包围的所有最短的字符串:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_65.jpg?sign=1739552410-PoGMyO5jhg0Z1me5NSCC2jrh9ELJ4H52-0-577721c0692b08ae8daea986d1bb525d)
注 意
在上述代码中没有字符串'picked a p',这是因为MATLAB从前向后查找字符串,当发现匹配的字符串后,继续从下一个字符开始向后查找,之前已查找过的字符将不会被重新查找。
用户可以使用圆括号将多个模式组合起来进行复合查找。例如,如下所示的代码用于在str中查找以p开头而不以i结尾的所有最长字符串:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_66.jpg?sign=1739552410-uhxTyD5hHGa6zFJVohRDI3XMu0NjOSkQ-0-a04cce793101230a57fc75c1c74b61a6)
在上述代码中使用了修正符“+”。如果在上述代码中加入圆括号,则表达式的意义将会发生细微的变化。例如,如下所示的代码在查找时,每次都会同时查找两个字符,返回所有由双字符“p×”(×为不是i的所有字符)构成的最长的字符串:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_67.jpg?sign=1739552410-Yk8mfW4DBunBjIwoi0HzCvdxbhoXyVpl-0-576132b89073c05d128b7a9576d45f3b)
由于在表达式中加入了圆括号,因此修正符“+”将作用于括号内的两个字符。
也可以再利用正则表达式在字符串中进行条件查找。MATLAB中提供了两种条件查找所用的操作符:逻辑操作符和范围操作符。范围操作符通常为查找限定了如下条件:被查找的字符串之后(或之前)具有(或不具有)另一个匹配字符串。
例如,如下所示的代码用于在str中查找所有以d结尾的单词之后的单词:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_68.jpg?sign=1739552410-InvnP3mezO7hQbEYapLK95S5NdzKtXgs-0-d50aac5a4c3f1fda5d8a94b542eb8fd1)
上述代码实际上返回的是位于字符d之后和到下一个空格符之前的那部分字符序列。
MATLAB中提供的标记表达式如表7-7所示。
表7-7 MATLAB中提供的标记表达式
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_69.jpg?sign=1739552410-4TaYLDl3rzPXbnyDv4KSGAuxgzyXLJBw-0-e4cf5e2eb4326cc9fa12aceeed96f428)
MATLAB中有3中种不同类型的正则表达式:第1种是前面使用的regexp()函数;第2种是regexpi()函数,该函数在查找时忽略大小写;第3种是regexprep()函数,该函数使用正则表达式替换字符串。
例如,如下所示的代码用于查找以'pi'开头的单词,并将这些单词保存起来,最后返回得到的字符串结果:
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_70.jpg?sign=1739552410-VauwsfjfFrLGfH12L5Z8pW2VxoY83bDU-0-b9e20312d2d80cd9a8e8fe920a4829b8)
上述代码产生了3个标记:第1个标记是字符串'picked',第2个标记是字符串'a peck of',第3个标记是字符串'pickled'。替换字符串'$3$2$1'告诉regexprep()函数删除原始字符串中与第1个参数相匹配的字符串,并使用与替换字符串标记相匹配的字符串来替换删除的字符串。原始字符串剩余部分将原封不动地返回。
在上例中,查找模式中的数字标记使用 \N语法,而替换字符串中的标记则使用 $n语法。
MATLAB中的正则表达式函数如表7-8所示。
表7-8 MATLAB中的正则表达式函数
![img](https://epubservercos.yuewen.com/FDADB4/20266983901431206/epubprivate/OEBPS/Images/txt008_71.jpg?sign=1739552410-pF2MBChVoGhdewb5cUxMb3CgrkhwzMks-0-ca65356c2ea809e061c34cb2c1b6b558)
在使用和修改上述正则表达式函数时,也可以使用多个选项,其中一个选项是前面已经用过的'match'参数。
在通常情况下,regexprep()函数是区分大小的,并且将替换它所查找到的所有子字符串,用户可以使用选项来改变该函数的这个默认设置。
以上3个函数既可以用于字符串单元数组,也可以用于单个字符串。用户既可以利用一个模式查找多个字符串,也可以利用多个模式查找多个字符串。
在编程时,这些函数的部分或全部的输入参数均可以使用字符串单元数组来表示。有关这些函数更详尽的信息,读者可以参考相应的MATLAB帮助文档。