吐槽
在开始之前请允许我展示一段正则:(?<=\s)\d(?=\s+)|(?<=\s)\d(?!\d+),在我没有学的时候了,我就感觉这NM是一段随便用键盘打的字,这是什么玩意,,,我当时是这么想的,真的没明白这是个什么东西。
但是相信我在学完以后,你一定会真香的!!
什么是正则表达式:
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。—来自百度百科
其实正则就是用来匹配字符串的,例如we are good,我们需要用正则找出空格,那么我们就需要使用\s+,或者[ ]来进行匹配。
学习正则需要的工具
我怕们学习正则,就要有相应的正则匹配的工具,这里推荐两个:RegexBuddy,MTracer
这两个的下载链接我放在文章末尾,有需要的自己去取一下哈~,
除了工具,我们可以用我们熟悉的语言进行实操,几乎所有的语言都实现了正则表达式,虽然每种语言各不相同,但是大同小异,正则的基本知识都是一样的。
正则中的部分概念:
元字符:
什么是元字符:元字符就是正则里面最基本的操作单元,最基本的元素;
元字符 说明 .(就是一个点) 用来匹配除了换行符以外的任意字符 \w 匹配字母/数字/下划线/汉字 \s 用来匹配任意的空白符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。 \d 匹配数字 \b 匹配一个字边界,即字与空格间的位置。例如,”er\b”匹配”never”中的”er”,但不匹配”verb”中的”er”。 ^ 匹配一个字符串的开始 $ 匹配一个字符串的结束
元字符的反义:
将元字符大写,就能匹配与之小写相反的字符
元字符 说明 \W 匹配不是字母/数字/下划线/汉字的字符 \S 用来匹配不是空白符的字符 \D 匹配任意的非数字 \B 非字边界匹配。”er\B”匹配”verb”中的”er”,但不匹配”never”中的”er”。 [^x] 匹配除了x以外的任意字符 [^aeiou] 匹配除了aeiou以外的字符
字符的转义
例如.是一个元字符,那么我就想去匹配点怎么办?在点前面加\即可
- \ 为转义字符
正则表达式中的注释
- #就是正则中的注释,但是最好别用,写出来的已经很难辨认了,你再加注释会被打的。。。
如果一定要使用注释话,请开启正则中”忽略模式里的空白符”选项
正则表达式中的重复
我们的字符串中肯定会出现重复的字符需要匹配,那么就用到我们的正则中的重复处理
元字符 说明 * 重复0次或者或者更多次 + 重复一次或更多次 ? 重复0次或者一次 {n} 重复n次 {n,} 重复n次或者更多次 {n,m} 重复n次到m次
正则表达式中的分支条件
- 用 | 把不同的规则分隔开
- 从左到右的测试每个条件,如果满足了某个分支的话,就不会再去管其他的条件了
字符串中的字符类
- [] 中括号里面写啥就匹配啥
[0-9] == \d 匹配0到9的数字
[a-z0-9A-Z] == \w 匹配0-9,A-Z,a-z的所有字符
[&?.] 匹配一些标点符号
[aeiou] 匹配一些字母
正则表达式中分组概念
- 将子表达式表示成子集
- 使用() 进行分组
- 方便对match后的字符串进行划分
- 分组是可以命名的:(?<groupname> exp) 那么分组的名字就是groupname
- (?:exp)匹配exp子组,但是不会捕获匹配到的文本也不会给分组分配编号,也就是将其从结果中剔除
贪婪与懒惰
- 贪婪就是尽可能多的匹配,写法是.*
给个例子:a.*b (aabab)->aabab,这就是贪婪的匹配结果- 懒惰就是尽可能少的匹配 .*?
匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复
还是那个例子: a.*?b (aabab) -> aab
元字符 说明 *? 重复任意次,但尽可能少的重复 +? 重复一次或者更多次,但尽可能少的重复 ?? 重复0次或者一次,但尽可能少的重复 {n,m}? 重复n次到m次,但尽可能少的重复 {n,}? 重复n次或者更多次,但尽可能少的重复 总之就是在这些后面加一个问号可以进行懒惰匹配。一般没有使用贪婪匹配的情况
正则表达式处理选项
元字符 说明 IgnoreCase(忽略大小写) 匹配时不区分大小写。 Multiline(多行模式) 更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) Singleline(单行模式) 更改.的含义,使它与每一个字符匹配(包括换行符\n)。 IgnorePatternWhitespace(忽略空白) 忽略表达式中的非转义空白并启用由#标记的注释。 ExplicitCapture(显式捕获) 仅捕获已被显式命名的组。 这种选项不知道是否在任意的语言中都支持。
反向引用
能看到这里的都是比较有耐心的大哥了,这后面属于一些正则的高阶用法,内容也比较抽象,我用的也不是很好
什么是反向引用呢,我的理解就是重复使用前面定义好的分组,不用自己重新去写了。
例如我写了一个 \b(\w)\b\s+\1\b ,这里的\1的意思就是(\w)。
- 想要重复指定分组的规则是:
1、如果子分组没有命名,就按照1,2,3,4这样去找子分组做反向引用
2、如果子分组做了命名,按照 \K<groupname>的方式做反向引用
零宽断言
- (?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I’m singing while you’re dancing.时,它会匹配sing和danc。
- (?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。
这里我很想吐槽一句,其实就是不占位置的前后匹配,但是这样取名字真的很难明白是啥意思。。反正我是理解了很久才明白是怎么回事
负向零宽断言
其实和零宽断言相反,就是匹配不占位的不是某种条件的情况
- 零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
- 零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。
还有个玩意叫平衡组/递归匹配
这个玩意好像只有.net有,这里不打算介绍了,我也没有仔细的去看,大家想学自己去百度把。。
至此正则的大部分内容已经说完了,后面就是实战部分。
常用的正则表达式:
表达式 说明 ^[0-9]*$ 数字 ^\d{n}$ n位数字 ^\d{n,}$ 至少n位数字 ^[\u4e00-\u9fa5]{0,}$ 汉字 ^\w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*$ Email地址 [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? 域名 这个我会持续补充,这里不做太多的介绍。
java如何写正则
Pattern类
Java提供了java.util.regex.Pattern 类来创建正则表达式对象
- public static boolean matches(regex, str) // 用来判断str是否匹配regex,或者说用来判断str是否符合regex的要求
public class Main { |
元字符的用法
- Java代码中的 \ 只表示正则中的 \
重复匹配
public class Main { |
其他正则匹配的使用方式与元字符的类似
Matcher类
public class Main { |
String也支持正则表达式
- String的方法中参数为regex的都是支持正则的。
- String newStr = str.replaceAll(regex, replacement);
- String[] newStrs = str.split(regex);//使用regex作为分隔符切分str
- boolean match = str.matches(regex);// 等同于Pattern.matches(regex, str)