正则表达式工做中一直在使用,可是没有系统的总结过,今天就从小白的角度梳理一下正则表达式的使用,主要关注的是正则的思想java
边写边听五月天的派对动物。学会了正则省下的时间就能够去party了 ^_^node
咱们先来看看正则表达式的概念,毕竟正则的语法、使用都是围绕着它要解决的问题来的。正则表达式
wikipedia定义:编程
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE), 又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法, 是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。 在不少文本编辑器里,正则表达式一般被用来检索、替换那些匹配某个模式的文本。
首先,正则表达式是一个字符串组成的模式,用来匹配一个字符串,通常用在检索,替换里,也常常用来校验一些字符模式,检验是否匹配一个给定的规则。编程语言
正则表达式使用字符串来描述字符串,也就是说跟编程语言,正则表达式是有本身的关键字
的,学会这些关键字是咱们入门正则的第一步,而后在使用中领会正则表达式的思想,一步步进阶。编辑器
首先要明确一点,正则引擎在匹配时是一个字符一个字符的匹配的,跟咱们日常印象中一串一串匹配的思惟是不一样的,这个须要咱们时刻牢记。工具
咱们首先来看一下匹配一个字符的关键字:日志
元字符 | 名称 | 含义 |
---|---|---|
. | 点号 | 匹配任意一个字符 |
[……] | 字符组 | 匹配组内的单个字符 |
[^……] | 排除性字符组 | 匹配单个未列出的字符 |
\meta | 转义字符 | 特殊含义或转义元字符 |
英文点号能够匹配任意字符,可是不包括换行符,也就是说匹配到换行点号就匹配失败了,咱们可使用\n
来匹配换行符,在java中也有MULTI_LINES
来指定让点号匹配到换行符code
若是咱们想匹配一个文本形式的点号怎么弄呢,可使用反斜线\
来转义关键字,这样就能够匹配一个点号,而不是匹配任意字符的关键字点号了。regexp
关于字符组须要说明一点,可使用-
来描述一个范围,好比咱们想匹配数字,咱们能够写一个全列[0123456789]
,也可使用[0-9]
,字符也是同样[a-zA-z]
匹配英文大小写的26个字母,若是咱们想匹配横杠怎么办呢?只有一个办法,那就是把它写在紧跟左中括号后面,[-a-z]
匹配横杠和a-z的全部字母,若是写在中间是会被当成关键字来解析的。
有了匹配单个字符的关键字,匹配多个就要用到计数元字符,经常使用的有下面这些:
元字符 | 名称 | 含义 | 区间表示 |
---|---|---|---|
? | 问号 | 匹配至多一次 | {0,1} greedy的 |
* | 星号 | 匹配任意屡次,也能够不匹配 | {0,} |
+ | 加号 | 匹配至少一次 | {1,} |
{min, max} | 区间 | min <=匹配次数 <= max | grep默认不支持{元字符,可使用-E选项 |
*?,+?,??,{min,max}? | 忽略优先量词 | 匹配尽量少的内容 | |
*+, ++, ?+ {min,max}+ | 占有优先量词 | 匹配内容后不会交还,相似固化分组 |
?*+
这三个元字符是可使用{}
来模拟的,不过在一些正则流派里不支持{}
元字符,咱们只能使用这三个。
在为加?
的量词上,前四个都是贪婪匹配的,也就是说他们会匹配尽量多的字符,在匹配失败的时候才会中止,这有时候颇有用,但有时候会让咱们没有通过深思写出来的正则匹配到错误的内容。第四列在量词后面加了?
则正相反,它会匹配尽量少的内容,是先为人后为几的,这两种方式的区别咱们后面再讲,这跟表达式引擎的递归与回溯有关。
最后一列是占有优先量词,这个概念是在贪婪的基础上加了铁公鸡属性(占有),也就是说经它匹配过的字符就是它的了,不会再吐出来。后面咱们在讲回溯跟固化分组时是再来回顾这个占有优先量词。
上面二者组合能够匹配大部分字符了,不过有些写起来很繁琐,所以正则为咱们提早定义好了一些简写,使用时能够减小表达式长度。
元字符 | 名称 | 含义 |
---|---|---|
\s | [ \f\v\t\n\r] | 匹配空格,制表符,回车、换行 |
\S | 除\s以外的任何字符 | |
\w | [a-zA-Z0-9_] | 匹配一个单词 |
\W | [^a-zA-Z0-9] | 匹配除\w外的任何字符 |
\d | [0-9] | 数字 |
\D | [^0-9] | 非数字 |
注:相同字母的小写跟大写在这是互补的,也就是互为补集,不过须要注意一点,在这里面没有包含Unicode字符,不一样的正则引擎对这些有不一样的实现,譬如\d
有的正则引擎能够匹配Unicode中的数字,也就是说中文六
也是有可能匹配的,这个能够参考各自的语言工具书(不过通常这样用没啥问题)。
我这里使用nodepad++来练习正则表达式,Linux下有些字符处理起来比较麻烦,Java写起来又太啰嗦,怎么简便怎么来。
找出一段文字中的数字
\d+
或 [0-9]+
这里使用加号是由于数字至少出现一次才是合法的,若是使用*
则能够匹配任意位置,由于*
能够不匹配任何字符
日志里常根据关键字和id来定位,通常如何使用呢?
假设关键字为keyword
, id为13235413
,而且id在后面,咱们可使用keyword.*13235413
来匹配含有这个模式的一行日志,这里加不加问号对咱们没有影响
找出一行里含有至少10个单词的行,假设单词以空格分割
这
是
自
己
的
思
考
线
不存在惟一的答案,我是这样写的(\w++ *){10,}
,第一次写成了(\w+ *){10,}
,也就是没有使用占有优先量词,这个表达式是不符合要求的,你们能够试一下,而后想一想,后面咱们会在涉及到回溯与固化分组相关的时候就能够明白了。