文章目录

  • 学习资源
  • 正则表达式
  • 正则表达式(REGEX)(Regular Express)
  • 一、概念
  • 二、元字符
  • 编程语言中的正则表达式
  • JavaScript
  • Java
  • C#
  • 正则表达式的常见用法
  • ip地址
  • 邮箱地址
  • 提取标签中的内容:以title为例
  • html注释
  • 网址url
  • QQ号码
  • 18位身份证


学习资源

书籍:正则表达式必知必会

正则表达式

正则表达式(REGEX)(Regular Express)

一、概念

正则表达式就是由普通字符以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式用来描述字符串的特征。

个人理解:正则表达式即用于检索、匹配、校验、替换字符串的文字模板。

作用

  1. **检索:**通过正则表达式,从字符串中获取我们想要的部分
  2. **匹配:**判断给定的字符串是否符合正则表达式的过滤逻辑
  3. 替换

正则表达式是非常复杂的,理解正则表达式能做什么(字符串匹配、字符串提取、字符串替换),掌握常用的正则表达式用法。

3个重要的正则表达式命令

  1. 在正则表达式中有三种类型的括号,[]、{}、()。中括号[]内是需要匹配的字符,大括号{}内是指定匹配字符的数量,小括号()则是用来改变优先级或分组的
  2. 插入符号"^"表示正则式的开始,在[]中表示“非”
  3. 美元符号"$"表示正则式的结束
    eg:Regex obj = new Regex("[a-z]{10}]");//搜索长度为10的a-z的英文字母
二、元字符
. 除\n以外的任意的单个字符		注:有且只有一个
[] 字符组:[]表示在字符组中罗列出来的字符,任意取单个。		eg:a[^a-zA-Z王]b		-表示范围,-在第一位时只表示一个字符,不表示元字符;^表示排除
以下是通配符:
| 表示“或”的意思			正则表达式尽量减少“|”的使用,“|”越多,越消耗性能
* 表示限定前面的表达式出现0次或者多次
+ 表示限定前面的表达式一次或多次,至少一次
? 表示限定前面的表达式出现0次或1次	
		注意.与*、+、?的区别
{} 指定匹配字符的数量		eg:[0-9]{8}		[a-z]{4,}

贪婪型量词和懒惰型量词

  • +、*和?也叫作量词
  • 区别
  • 前者会尽可能多地匹配,后者会尽可能少的匹配
  • 贪婪型会尽可能从一段文本的开头匹配到结尾,懒惰型碰到第一个匹配后就会停止

贪婪型量词

懒惰型量词

*

*?

+

+?

{n,}

{n,}?

eg:

文本
this offer is not available to customers living in <b>AK</b> and <b>HI</b>

正则表达式	贪婪型
<[Bb]>.*<\/[Bb]>
结果:一处匹配	<b>AK</b> and <b>HI</b>

正则表达式	懒惰型
<[Bb]>.*?<\/[Bb]>
结果:两处匹配	<b>AK</b>		<b>HI</b>
[0-9]	\d		\D取余
[A-Za-z0-9_]	\w		\W取余
[\f\n\r\t\v]	\s	表示所有不可见字符		\S取余
\b单词边界		\B取余.	\b匹配的是字符之间的一个位置:一边是能够被\w匹配的字母数字和下划线,另一边是能够被\W匹配的字符

\x	十六进制
\o	八进制
\uxxxx匹配Unicode编码

注:要想完全匹配,必须要加^和$

反向引用

反向引用:子表达式用来定义字符或表达式的集合。除了可以用于重复匹配,还可以在模式的内部被引用,这种引用被称为反向引用。

eg:查找重复单词

this is a block of of text

正则表达式:[ ]+(\w+)[ ]+\1

this is a block of of text

\1表示匹配模式中所使用的第一个子表达式,\2,\3…以此类推

  • 可以把反向引用想象成变量
  • 反向引用只能用来引用括号里的子表达式
  • 反向引用匹配通常从1开始计数看,\0可以用来代表整个正则表达式

eg:匹配正确的标题标签内容

<h3>fasd</h3>
<h2>fasd</h3>

<[Hh](1-6)>.*?</[Hh]\1>

环视(lookaround)

环视:该模式是为了找出正确的匹配,而其自身不属于最终的匹配结果。分为向前查看和向后查看。环视可以更精细地控制最终的返回结果

  • 所有语言都支持向前查看,java支持向后查看,js不支持向后查看
  • 向前查看模式长度可变,比较灵活;向后查看只能是固定长度
  • 否定式环视,即不包含

种类

说明

(?=)

肯定式向前查看

(?!)

否定式向前查看

(?<=)

肯定式向后查看

(?<!)

否定式向后查看

eg:提取url的协议部分

http://www.baidu.com
https://mail.forta.com
ftp://ftp.baidu.com

正则表达式:.*(?=:)

http😕/www.baidu.com
https😕/mail.forta.com
ftp😕/ftp.baidu.com

结果中就不包含“:”

eg:结合向前查看和向后查看,提取标题中的文本内容(不包含标题)

<title>dfshal</title>

正则表达式:(?<=\<[Tt][Ii][Tt][Ll][Ee]).*(?=</[Tt][Ii][Tt][Ll][Ee]>)

<title>dfshal</title>

编程语言中的正则表达式

JavaScript

两种创建方式:

  1. 直接量
var reg = /abc/im;
	i:ingoreCase
	g:global,全局匹配(查找所有匹配而非在找到第一个匹配后停止)
	m:multiline,执行多行匹配
  1. new RegExp(“正则表达式”);

reg.test(),检测是否匹配

str.match(reg),返回匹配数组

Java

java.util.regex包

  • Pattern 正则表达式的编译表示
  • compile 编译一个正则表达式为Pattern对象
  • matcher 用Pattern对象匹配一个字符串,返回匹配结果
  • Matcher
  • Index Methods(位置方法) //start(),start(int group),end(),end(int group)
  • Search Methods(查找方法) //lookingAt(),find(),find(int start),matches()
  • lookingAt()//部分匹配
  • matches()//完全匹配
  • Replacement Methods(替换方法) //replaceAll(String replacement)

eg

private static final String REGEX = "\\bdog\\b";//\b表示边界private static final String INPUT = "dog dog dog doggie dogg";public static void main(String[] args) {    //检查字符串里面有多少个dog    Pattern p = Pattern.compile(REGEX);    Matcher m = p.matcher(INPUT);    int count = 0;    while (m.find()) {        count++;        System.out.println("count = " + count);        System.out.println("m = " + m.start());        System.out.println("m.end() = " + m.end());    }}
private static final String REGEX = "Foo";private static final String INPUT = "Foooooooo";private static Pattern pattern;private static Matcher matcher;public static void main(String[] args) {    //Initialize    pattern = Pattern.compile(REGEX);    matcher = pattern.matcher(INPUT);    System.out.println("REGEX = " + REGEX);    System.out.println("INPUT = " + INPUT);    System.out.println("matcher.lookingAt() = " + matcher.lookingAt());//部分匹配    System.out.println("matcher.matches() = " + matcher.matches());//完全匹配}
private static String REGEX = "a*b";//*表示限定前面的a可以有0或多个private static String INPUT = "aabfooaabfooabfoobcdd";private static String REPLACE = "-";public static void main(String[] args) {    Pattern pattern = Pattern.compile(REGEX);    Matcher matcher = pattern.matcher(INPUT);    StringBuffer stringBuffer = new StringBuffer();    //全部替换    while (matcher.find()) {        matcher.appendReplacement(stringBuffer, REPLACE);    }    //将最后的尾巴字符串附加上    matcher.appendTail(stringBuffer);    System.out.println("stringBuffer.toString() = " + stringBuffer.toString());}
private static String REGEX="dog";private static String INPUT="The dog says meow.All dogs say meow.";private static String REPLACE="cat";public static void main(String[] args) {    Pattern pattern=Pattern.compile(REGEX);    Matcher matcher=pattern.matcher(INPUT);    INPUT=matcher.replaceAll(REPLACE);//将所有的dog换成cat    System.out.println("INPUT = " + INPUT);}
C#

添加引用

using System.Text.RegularExpressions;

常用方法

IsMacth():	用来判断给定的字符串是否匹配某个正则表达式Match():	用来从给定的字符串中按照正则表达式的要求提取【一个】匹配的字符串		一般字符串提取不加^和$Matches():	【所有】匹配的字符串Replace():	替换字符串
Match.Value表示本次提取到的字符串Match.Groups集合中存储的就是所有的分组信息Match.Groups[0].Value	表示这次提取的整个字符串Match.Groups[1].Value	表示这次提取的字符串中的第一个分组字符串

正则表达式的常见用法

ip地址
(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))
邮箱地址
(\w+\.)*\w+@(\w+\.)+[A-Za-z]+
提取标签中的内容:以title为例
(?<=\<[Tt][Ii][Tt][Ll][Ee]).*(?=\<\[Tt][Ii][Tt][Ll][Ee]>)
html注释
(?<=\<!--\s*).*(?=\s*-->)
网址url
[a-zA-z]+://[^\s]*
QQ号码
[1-9][0-9]{4,}
18位身份证
^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$