文章目录
- 学习资源
- 正则表达式
- 正则表达式(REGEX)(Regular Express)
- 一、概念
- 二、元字符
- 编程语言中的正则表达式
- JavaScript
- Java
- C#
- 正则表达式的常见用法
- ip地址
- 邮箱地址
- 提取标签中的内容:以title为例
- html注释
- 网址url
- QQ号码
- 18位身份证
学习资源
书籍:正则表达式必知必会
正则表达式
正则表达式(REGEX)(Regular Express)
一、概念
正则表达式就是由普通字符以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式用来描述字符串的特征。
个人理解:正则表达式即用于检索、匹配、校验、替换字符串的文字模板。
作用
- **检索:**通过正则表达式,从字符串中获取我们想要的部分
- **匹配:**判断给定的字符串是否符合正则表达式的过滤逻辑
- 替换:
正则表达式是非常复杂的,理解正则表达式能做什么(字符串匹配、字符串提取、字符串替换),掌握常用的正则表达式用法。
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
两种创建方式:
- 直接量
var reg = /abc/im;
i:ingoreCase
g:global,全局匹配(查找所有匹配而非在找到第一个匹配后停止)
m:multiline,执行多行匹配
- 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)$