码迷,mamicode.com
首页 > 其他好文 > 详细

正则表达式学习

时间:2020-03-25 13:25:52      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:第一个字符   分类   字段   元字符   怎么   空格   this   数字   对象   

定义

正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a到z之间的字母)和特殊字符(称为"元字符")。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

基本语法

单个字符

  • \d 匹配一个数字字符。等价于[0-9]。
  • \w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
  • \W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
  • \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
  • \S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
  • . 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。

例子

假设有一段话如下:

These are some phone numbers 917-555-1234. Also, you can call me
at 646.555.1234 and of course I‘m always reachable at (212)867-5309.
  • \w 将将匹配任何单词字符,当然,() - 等字符除外
  • \w\w\w 发现匹配的有‘These are some phone numbers ...‘ 注意正则表达式是匹配一个连续串的规则,所以可以看到三个字母的单词可以匹配到,6个单词的也可以匹配到。
  • \s\s 匹配到一行中连续两个空格

数量

  • * 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
  • + 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
  • ? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
  • {n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
  • {n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。

例子

假设有一段话如下:

The colors of the rainbow have many colours
and the rainbow does not  have a single colour.

我们想把所有的“颜色”找出来,即colors colours colour
可用colou?rs?

另外也可以匹配一行中的4个数字,或者一行中的5个字母。如找5个字母组成的单词:

  • \w{5} 这样可以吗?不行的,看下它匹配的内容,如下:
    These are some phone numbers 915-555-1234...
    的确,我们模板给的很简单,它只找一行中,连续出现5个字母的序列。

  • \w{5}\s 为了能找到单词,所以希望5个字母后,跟一个空格的序列,看下匹配情况:
    These are some phone numbers 915-555-1234...
    可以得出,只有目前这些方法,是做不到的。

位置

  • ^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
  • $ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
  • \b 匹配一个单词边界,也就是指单词和空格间的位置。

例子

This is somthing
is about
a blah
words
sequence of words
Hello and
GoodBye and
Go gogo!

来看下各种正则所匹配的内容:

  • \w+ 这个应该毫无疑问,匹配所有的words
  • ^\w+ 多了一个^,这样子,就只能匹配到每一行开头的单词了This is a words sequence Hello GoodBye Go
  • \w+$ 这样就能匹配到每行的最后一个字母

回到刚才的问题:现在想找5个字母组成的单词,是使用单词结界符\b,答案即\b\w{5}\b。

字符分类

找个电话号码

找一个刚才出现的电话号123-456-1231:
用以上最基本的正则方法就是 \d{3}-\d{3}-\d{4},这样就找到了。但是有的时候,电话号码是(212)867-4233的结构怎么办呢?正则表达式中的其他表达方式,下面一一来介绍。

分类符

分类符[]用来表示逻辑关系或,比如[abc]表示a或者b或c,[-.]表示符号-或者.号。
注:在[]中的.号代表的就是这个符号,但是如果在其外面,表示个匹配所有。所以如果不在[]之中,想要匹配‘.‘,就要通过转意符号\.来进行匹配。

例子

字符序列:The lynk is quite a link don‘t you think? l nk l(nk
正则表达式: l[yi (]nk
结果:lynk link l nk l(nk

匹配所有可能的电话号码

有以下字段,请匹配所有可能的电话号码:

These are some phone numbers 915-134-3122. Also,
you can call me at 643.123.1333 and of course,
I‘m always reachable at (212)867-5509

一步一步来,刚才我们使用\d{3}-\d{3}-\d{4}匹配了连字符的情况。现在我们可以很轻松的把 . 这种情况加进去了:

  • 第一步: \d{3}[-.]\d{3}[-.]\d{4}
  • 第二步: 为了能够匹配括号,可以使用?来,因为这是一个option选择。所以最后就成了(?\d{3}[-.)]\d{3}[-.]\d{4}

这里还是要说明,在[]中,特殊字符不需要转义,可以直接使用,比如[.()],但是在外面,是需要转义的( .等。

[]的特殊语法

刚才介绍了最简单和基本的功能,但是有些特殊的地方需要注意:

  1. -连接符是第一个字符时:比如[-.]的含义是连字符-或者点符 . 。 但是,如果当连字符不是第一个字符时,比如[a-z],这就表示是从字母a到字符z。
  2. []中的^: ^在之前介绍中,是表示一行开头,但是在[]中,有着不同的含义。[ab] 表示a或者b,[^ab] 啥都行,只要不是a或b(anythings except a and b),相当于取反。

[]和()

除了使用[]表示或逻辑,()也是可以的。用法是(a|b)表示a或者b。比如下面的例子,匹配所有email:

  1. 任何一个以words开头的,一个或更多: \w+
  2. 紧接着是一个@符号: \w+@
  3. 接着有一个或者更多的words: \w+@\w+
  4. 接着一个.标点(注意转义): \w+@\w+.
  5. 接着一个com net 或 edu: \w+@\w+.(com|net|edu)

这样就可以匹配邮箱了。但是还有一个问题,因为邮箱用户名是可以有.的,比如XXXX@126.com
其实仍然很简单,修复如下:[\w.]+@\w+.(com|net|edu)

小结

  1. []的作用,用英文表达就是"alternation",表达一个或的逻辑;
  2. /[-.(]/ 在符号中的连字符-放在第一位表示连字符本身,如果放在中间,表示"从..到..",比如[a-z]表示a-z
  3. [.)] 括号中的特殊符号不需要转义,就表示其本身
  4. [^ab] 括号中的^表示非,anythings except a and b
  5. (a|b)也可表示选择,但是它有更强大的功能....

所以,()的强大功能是什么呢? 分组捕获,这对序列的替换、交换是很有帮助的。后面会提到。

分组捕获

回到之前电话号码的例子,保留区号,并把后面的电话号码变为通用性的:

212-xxx-xxxx
915-xxx-xxxx
  • 按照之前的做法\d{3}-\d{3}-\d{4},这种匹配的方式,是将整个电话号码作为一个组(group)匹配起来。 我们把212-555-1234这样的叫Group0。
  • 这个时候,如果我们加了一个括号\d{3}-(\d{3})-\d{4},那么匹配到的555就叫Group1。
  • 以此类推,如果有两个小括号\d{3}-(\d{3})-(\d{4})那么分组就是下面的情况:
212-555-1234   Group0
555            Group1
1234           Group2

选择分组

组已经分好,有两种方法选择已经匹配的分组:

  1. 使用$符号,比如$1代表555,$2代表1234
  2. 使用\,比如\1代表555。

现在把212-555-1234变成212-xxx-xxxx,表达式如下:

reg: \(?(\d{3})[-.)]\d{3}[-.]\d{4}
replace: $1-xxx-xxxx

例子

  1. 现在有一个名单列表,但是姓和名称是反的,需要进行交换:
shiffina, Daniel
shifafl, Daniell
shquer, Danny

实现方法:

reg: (\w+),\s(\w+)
replace: $2 $1

注意:$0 是所有匹配到的,所以第一个加括号的是$1

  1. 匹配markdown中的link标签,并替换为html标签:
[google](https://google.com)
[itp](https://itp.nyu.edu)
[Coding Rainbow](https://codingrainbow.com)

此题易错,看到[google]时最易想到的正则表达式是\[.*\],但如果第一行变成:

[google](https://google.com),[test]

那么,这一整行都会被匹配。而不能区分[google]和[test]。原因是 . 是贪婪的,会匹配所有能匹配到的,所以当然也包括了 ] ,一直到这一行的最后一个 ] ,它才停止。
所以为了让它能正确匹配,需要去掉这种贪婪的属性。这里用到 ? 。

 ? 字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。

即如\[.*?\],就可以将[google]和[test]分开。那么,匹配所有内容用的表达式如下:

reg: \[(.*?)\]\((https.*?)\)
replace: <a href="$2">$1</a>

正则表达式学习

标签:第一个字符   分类   字段   元字符   怎么   空格   this   数字   对象   

原文地址:https://www.cnblogs.com/leosyn1998/p/12565551.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!