正则表达式

人走茶凉 提交于 2020-04-08 02:13:47

基础

需要谨记的3个字母

\d

匹配数字

\w

匹配字母、数字、下划线

\s

匹配空白符(例如空格、换行符、制表符等)

大写表示匹配其相反的东西,如:\D 匹配非数字字符,\S匹配非空白字符

 

常用的匹配字符

[0-9]

匹配在此区间的数字,同\d

[a-zA-Z]

匹配在此区间的字母,可以多个区间一起

[x.|9\\]

匹配在中括号内的字符,里面的都是普通字符没其他含义,除斜杠比较特殊需转义

[^a8]

匹配除中括号内字符之外的字符,和上面3个字母大写匹配其相反的东西一样的道理

hello

匹配常规字符串

^hello

匹配行首的hello

hello$

匹配行末的hello

hello|world

匹配hello或者world(正则中没有与运算)

.

匹配除换行符(\n、\r)之外的任意字符

[\u4e00-\u9fa5]

匹配中文字符

[\s\S]

匹配任意字符(随便两个互补区间都可以表示任意字符)

 

表示字符数量的描述符(描述前面子表达式的匹配数量)

*

零次或多次

+

一次或多次

?

零次或一次

{n}

整数n

{n,m}

n~m次,包含nm

{n,}

n次以上,包含n

默认是描述前面一个字符,如果是多个字符的子表达式,需要括号括起来。

如:(pattern)*     th(is|at)       括号别有用处,后面会讲到

 

进阶

获取匹配与非获取匹配

(pattern)

 

这里用括号将匹配子表达式括起来,从匹配结果来看加括号不影响正常匹配。

加括号主要是为了获取该子表达式匹配到的内容

获取匹配,怎么用我们后面会讲到

(?:pattern)

如果我们加括号只是为了圈定一串子表达式,而不用获取匹配到的内容。

上面的例子我们最好这样  th(?:is|at),等同于this|that

非获取匹配

hello(?=world)

如果一字符串包含多处hello,只匹配后面跟着worldhello,匹配结果不包含world

例如,"Windows(?=95|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows98"中的"Windows"

非获取匹配

hello(?!world)

同理,只匹配后面没跟着worldhello,匹配结果不包含world

非获取匹配

(?<=hello)world

如果一字符串包含多处world,只匹配前面跟着helloworld,匹配结果不包含hello

例如,"(?<=95|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"98Windows"中的"Windows"

非获取匹配

(?<!hello)world

同理,只匹配前面没跟着helloworld,匹配结果不包含hello

非获取匹配

 

非贪婪匹配

举个例子:"hello world and hi world"  我们需要匹配其中的"hello world""hi world"

  1. 我们可以这样子h.*world,但是我们运行后发现匹配到的结果是"hello world and hi world",这结果也没毛病,确实符合我们写出来的正则表达式。
  2. 如何得到我们想要的结果呢,我们这样子h.*?world,就能匹配到"hello world""hi world"

贪婪匹配:尽可能匹配最长的字符串

非贪婪匹配:尽可能匹配最短的字符串

个人对非贪婪匹配的理解是:从左往右匹配到符合正则的最短结果,返回结果并继续往后匹配下一结果。

 

扩展(思考)

匹配typepasswordinput标签: <input type=radio name=xxx><input type=password name=yyy><input type=txt name=zzz>

  1. <input.*password.*>  匹配得到  <input type=radio name=xxx><input type=password name=yyy><input type=txt name=zzz>
  1. <input.*password.*?>  匹配得到  <input type=radio name=xxx><input type=password name=yyy><input type=txt name=zzz>
  1. <input((?!input).)*password.*?>匹配得到<input type=radio name=xxx><input type=password name=yyy><input type=txt name=zzz>

第一步写出匹配的轮廓,第二步使用非贪婪匹配排除掉后面部分,第三步inputpassword之间的字符串排除input

 

个人对((?!input).)*的理解:

  1. (?!input)i 匹配所有位置的‘i’,但不包括input开头的‘i’,即后面跟着nputi都不匹配。
  2. (?!input).  匹配任意字符(点的作用),但不包括input开头的‘i’。
  3. ((?!input).)*  匹配零个或多个(2)中的字符,既然input开头的‘i’被排除了,那么也就不存在input字符串了。

 

应用

java演示group

  • 获取匹配

public static void main(String[] args) {

String str = "Her name is John, Her age is 18";

str += "Her name is Mike, Her age is 15";

Pattern pattern = Pattern.compile("Her name is (\\w+), Her age is (\\d+)");

Matcher matcher  = pattern.matcher(str);

matcher.groupCount(); //获取匹配数量

while (matcher.find()) {

System.out.println(matcher.group());   // 输出整条正则表达式匹配到的内容

System.out.println(matcher.group(1) + " " + matcher.group(2));  // 输出括号中子表达式匹配到的内容

}

}

结果:

Her name is John, Her age is 18

John 18

Her name is Mike, Her age is 15

Mike 15

 

  • 给group取别名,通过别名获取匹配(不影响表达式的正则匹配)

Pattern pattern = Pattern.compile("Her name is (?<name>\\w+), Her age is (\\d+)");

matcher.group(name);

 

linux命令grep使用正则

 

python使用正则

 

 

练习/训练

http://tool.chinaz.com/regex/

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!