首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

学R学初阶_01_R中的正则表达式

本讲主要介绍正则表达式(regular expression,regex)的概念、主要语法风格以及在R中的使用方法。欢迎转载,但请注明出处!

为何讲它

我在学习The Art of R Programming第35页的时候遇到一个练习,我想用模式匹配去解决,也就是regex,但遇到了未曾料到的问题,于是我在stackoverflow上提问了,大牛的解答让我想要集中几天精力搞清楚regex到底怎么用,问题见此:my question,不巧被标记了重复…

regex是一个相对独立的内容,几乎所有编程语言都实现了这种功能,这也证明了它的重要性,另外,本讲标题序号虽然是01,但大家可以放在遇到实际问题时再来学,那样有了共鸣,印象会更深刻!

正则表达式

我们在面对生物数据,尤其是序列信息(比如碱基序列、氨基酸序列等)的时候, 会时常想要问自己,这其中是否包含着且含有多少某种已知的模式,一段DNA中是否包含转录起始特征TATA box、一段RNA中是否包含某种lncRNA、一段肽链中是否包含锌指结构等等;另一方面,我们在操作数据时,会时常遇到诸如把某个字符(对象)换成另一种字符(对象)的替换操作,而其本质还是如何搜索符合某种(替换)模式的对象。

在这些几乎天天都可以碰到的模式匹配/搜索问题中,正则表达式就是一把解决问题的利剑!

正则表达式:它是一连串用来描述模式的字符,它的书写遵循一定的语法规则,当用户进行文本匹配的时候,程序语言会调用预设的引擎(其实就是内置的或第三方库里的软件包),利用正则表达式去搜索符合模式的文本信息!英文名是regular expression,常缩写为regex,或regexp。

知道英文名后,大家就应该不用去纠结“正则”这个反人类名词了,你可以理解为规则的、规范的,或者直接叫它“模式表达式”。多说一句,劝大家学习时尽量阅读英文材料,中文材料中很多硬生生的翻译,不仅不能达意,还会让很多人产生误解!

语法风格

由以上概念,我们大概会以为正则表达式就像一种模式书写规范,它应该是唯一的,且被大多数编程语言所共用。然而,事情却不那么优雅,从regex诞生之日起,先后产生了数十种适应于不同程序语言的语法规则和风格,而且有些语言还实现了不只一种语法规则,比如R。其中流传最广的一种是:POSIX (Portable Operating System Interface for uniX)标准下的BRE (Basic Regular Expression)、ERE (Extended Regular Expression);另一种则是PCRE (Perl Compatible Regular Expressions),详情请参考regular expression in wiki。

在R语言(版本>R 2.10.0)中,它使用了两种语法规则:默认的是Ville Laurikari’s TRE,还有一种就是PCRE。

在本讲中,我使用的是高效且被广泛使用的PCRE语法,同样也推荐大家使用,操作很简单,只需在相应的R函数里加上 参数即可调用此语法,在后面的内容中大家会看到!

常用语法

虽然说regex有很多种语法风格,但毕竟人是比较懒的,既然有前人的轮子在,而且用起来也很不错,那么就不会有人愿意从头再造一遍,所以这些语法大同小异,下面我将介绍一些PCRE中常用的语法规则。(以下内容多数引用自learn regex the easy way)

基本匹配

“the” => The fat cat sat onthemat.

“The” =>Thefat cat sat on the mat.(默认大小写敏感)

元字符(meta characters)

所谓的meta-X(中文翻译成“元”啊,“宏”啊,“后设”啊,先可以不管),在英文中代表概念X背后的概念,而每个meta词汇又有其特有的解释方法,比如data是数据(如工资表),meta-data则是描述这个工资表的数据(什么纸打印的,用的哪种墨盒,存放在哪个档案库等等)。此处的meta characters,指的是这些字符虽然本质是字符,但并非是它们字面(literal)上的意思,而是我们赋予的新的意思,“后设”的意思!

句号(period):通配符,可以匹配单个除了换行符(newline)之外的所有字符。

=> Thecarparked in thegarage.

字符集(character set):括号中的字符都可以用来匹配,但只能匹配单个位置,如果用短横线隔开,表示一个范围,例如[a-z],表示从a到z中间所有字符,包括两端。

=>Thecar parked inthegarage.

取反字符集(negated character set):括号中的字符都不可用来匹配。

=> The carparked in thegarage.

计数字符, , (repetition):

:前一个字符重复1次至多次 => The fatcat sat on the mat.

:前一个字符重复0次至多次 => The car parked in the garage#21.

:前一个字符重复0次或1次 =>Thecar is parked in thegarage.

计数区间:和前一条类似,只不过指明了重复次数在n和m之间,包含两端。注意表示只重复n次,表示重复大于等于n次。

=> The number was 9.9997 but we rounded it off to10.0.

亚模式(subpattern):用小括号括起来的字符串属于一个固定的模式,需要不偏不倚的被匹配到。

=> The car is parked in the garage.(代表空格)

或者(alternation):或然关系,匹配到其中一个即可。

=>The caris parked inthegarage.

首尾匹配,表明后面的字符一定是处于第一的位置,而表明之前的字符一定是处于最末的位置,见例子:

=>Thecar is parked in the garage.

=> The fat cat. sat. on the mat.

缩写字符集(shorthand character sets)

前后看(lookaround)

这个语法也就是开头提到的、那个让我解决不了的问题的核心,其实学会了它后,你会感觉很有意思。

假设一下,如果我们想找的模式X周围还有特定的亚模式Y,该怎么办?你可以直接匹配你要的模式X,但如果有些X旁边没有Y,我们该怎么排除出去呢?这时候“前后看”就派上大用场了,我们以Y为眼睛,让它看看四周有没有X,有的话就直接匹配上!

向前看(positive lookahead):顾名思义,是匹配Y前面的X。

=>Thefat cat sat on the mat.

向前删(negative lookahead):和上面相反,是匹配Y前面的X。

=> The fat cat sat onthemat.

向后看(positive lookbehind):匹配Y后面的X。

=> Thefatcat sat on themat.

向后删(negative lookbehind):匹配Y后面的X。

=> The cat sat oncat.

有一点要注意的是,lookaround中的模式,即上面的模式Y,是不会被引擎捕获到的,这一点在某些特定情况下还蛮有用的,请参看my question。

PCRE本身的语法还有不少,但常用的基本都在这里了,如果想深入了解,请参考PCRE syntax。

R中怎么使用

前面提到,R实现了两种regex语法风格,个人推荐使用PCRE风格,不然前面的也白看了不是?R中常用的模式匹配操作,一是运用包中的几个函数,二是利用包中的系列函数,本文只介绍前者,在熟练之后,大家应该去学习下后者,大神出品,方便易用,参见R for data science - Strings。(以下内容多数引用自Regular Expressions with The R Language)

匹配

函数:”grep”的意思是”global search forregularexpression andprint matching lines”,这是最核心的函数,其他的几个函数与之大同小异。第一个参数是pattern,即模式;第二个则是input,即需要被匹配的文本。当时,给出匹配上的元素的位置,而则会直接给出匹配上的元素。

函数:”l”在这里是”logical”的缩写,所以,你可以猜到,这个函数给出的结果是一串逻辑值。

函数:上面的函数只能告诉你哪些文本被匹配上了,但如果我们需要知道具体匹配的位置,就需要用到和函数了。除了没有参数外,函数的写法与上面完全一样,但得到的结果则是对应于每个input的元素、模式从左至右第一次被匹配到的位置!如果没有匹配上,会显示。

可以看到,函数返回的结果是一个和input等长的vector,其中包含的是首次匹配上的位置,这个vector还含有两个属性(attributes),第一个给出的是匹配上的文本的长度,比如这里第四个,匹配上的是,所以长度是2;第二个暂时不用管它。

函数:它比上面的兄弟多了一个”g”,你可能已经猜到,这是个global匹配函数,与唯一的区别是,它返回的值是一个list,针对input中的每个元素,都会给出所有匹配上的位置。

函数:前面的函数中,如果设置,那么会给出每个匹配上的元素的整体(比如用”a”去匹配”abc”,会得到”abc”),而如果我们需要的仅仅是匹配上的部分(即”a”),就能派上用场了。这个函数需要的参数一个自然是模式,另一个则是或返回的值,因为其中包含了匹配上的位置。

替换

和函数:顾名思义,需要有三个参数,模式、替换文本、原文本(pattern, replacement, input)。区别也很明显,是首位匹配,是全局匹配。

更为直接的方式是,利用前面提到的函数,因为它得到刚好仅仅是匹配上的值,那么给这个函数赋予一个vector,里面包含替换文本,即可更改原文本

结语

regex用途非常广泛,但当你初次接触时,会有一段时间的羞涩期,不用担心,这是正常的,很快你就会发现它的好,欲罢不能。regex本身是包含很多深层次内容的,本讲的介绍只是蜻蜓点水、管中窥豹,所以难免挂一漏万,如有错误,还望不吝指正。

要想把regex用得熟、用得好,必须要有一定的训练量!所以最后,给出一些不错的学习资源,望大家继续钻研。

regex-info

regex-online-learning

Regular-Expressions-Cookbook

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180309B09KG500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券