正则表达式
正则表达式
正则表达式,又称规则表达式,是一种文本模式,用来根据模式检索、替换和控制文本。
元字符
元字符 | 说明 |
---|---|
. |
匹配除了换行符之外的任意字符 |
\d 或[[:digit:]] |
匹配数字 |
\s |
匹配任意空白符 |
\w |
匹配字母,数字,下划线,汉字 |
^ |
匹配字符串的开头 |
$ |
匹配字符串的结尾 |
\b 或\< ,\> |
匹配单词的开头或结尾 |
常用正则表达式 | 语法 |
---|---|
匹配空行 | ^$ |
匹配完整单词 | \bword\b 或\<word\> |
重复限定符
重复限定符 | 说明 |
---|---|
* |
重复0次或无数次 |
+ |
重复1次或无数次 |
? |
重复0次或1次 |
{n} |
重复n次 |
{n,} |
重复n次或无数次 |
{n,m} |
重复n到m次 |
区间
正则提供一个元字符中括号[]
来表示区间条件。
区间范围 | 语法 | 替代语法 |
---|---|---|
字符. ,此时不为元字符 |
[.] |
|
离散字符1 ,a ,B |
[1aB] |
|
0到9 | [0-9] |
[[:digit:]] |
非0到9 | [^0-9] |
[^[:digit:]] |
a到z | [a-z] |
[[:lower:]] |
A到Z | [A-Z] |
[[:upper:]] |
任意字母 | [a-zA-Z] |
[[:alpha:]] |
任意字母和数字 | [a-zA-Z0-9] |
[[:alnum:]] |
任意空白符 | [[:space:]] |
|
任意标点符号 | [[:punct:]] |
常用正则表达式 | 语法 |
---|---|
匹配空白行 | ^\s*$ |
反义
元字符 | 说明 |
---|---|
\W | 匹配任何不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字字符 |
\B | 匹配任意不是单词的开始或结束的位置 |
[^x] | 匹配任意不是x的字符 |
[^aeiou] | 匹配任何不是元音的字符 |
分组
正则表达式中用小括号()
来做分组,也就是括号中的内容作为一个整体。因此当我们要匹配多个ab
时,可以这样:
(ab)*
常用正则表达式 | 语法 |
---|---|
匹配正整数 | (0|[1-9][0-9]*) |
匹配小数 | (0|[1-9][0-9]*)([.][0-9]+)? |
转义
正则提供了转义的方式,在要转义的字符前面加个斜杠,也就是\
即可。当我们要匹配(ab)
时,可以这样:
(\(ab\))*
条件或
正则用符号|
来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。
(123|456)
零宽断言
- 正向先行断言(正前瞻):
- 语法:
(?=pattern)
- 作用:匹配pattern表达式的前面内容,不返回本身。
- 语法:
- 正向后行断言(正后顾):
- 语法:
(?<=pattern)
- 作用:匹配pattern表达式的后面的内容,不返回本身。
- 语法:
其实这个零宽断言听起来好复杂,但其实很简单。主要的作用就是用断言的pattern
去去定位你真正想要的数据。
比如有下面的应用程序应用,你只想得到running
的进程数量。那么就可以用后行断言,来得到指定pattern
后面的数据。
[rc@localhost work]$ cat info.log
running processes: 233
stopped processes: 23
[rc@localhost work]$ cat info.log | grep -o -P "(?<=running processes: )[0-9]*"
233
贪婪和非贪婪
- 贪婪
- 贪婪匹配:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,这匹配方式叫做贪婪匹配。
- 特性:一次性读入整个字符串进行匹配,每当不匹配就舍弃最右边一个字符,继续匹配,依次匹配和舍弃(这种匹配-舍弃的方式也叫做回溯),直到匹配成功或者把整个字符串舍弃完为止,因此它是一种最大化的数据返回,能多不会少。
- 懒惰
- 懒惰匹配:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能少的字符,这匹配方式叫做懒惰匹配。
- 特性:从左到右,从字符串的最左边开始匹配,每次试图不读入字符匹配,匹配成功,则完成匹配,否则读入一个字符再匹配,依此循环(读入字符、匹配)直到匹配成功或者把字符串的字符匹配完为止。
默认情况下,上面介绍的重复限定符都是贪婪匹配模式。懒惰量词是在贪婪量词后面加个?
。
懒惰重复限定符 | 说明 |
---|---|
*? |
重复任意次,但尽可能少 |
+? |
重复一次或多次,但尽可能少 |
?? |
重复0次或1次,但尽可能少 |
{n,m}? |
重复最少n次最多m次,但尽可能少 |
{n}? |
重复最少n次,但尽可能少 |
[rc@localhost work]$ cat text
hellooooooo
[rc@localhost work]$ cat text | grep -o -P "hello+?"
hello
[rc@localhost work]$ cat text | grep -o -P "hello+"
hellooooooo
分组与后向引用
对于每一个()
内的分组,会进行分组编号,按左边括号出现的顺序从1开始编号(0表示正则表达式本身)。
有了这个分组编号之后就可以对其进行引用,表示按照目标分组进行相同的匹配,这样就可以匹配更复杂的需求。
比如现在有一个文本,每行都是三个单词,现在要求匹配第一个单词和第三个单词相同的行。
[rc@localhost work]$ cat text
hello world hello
you me him
ok no ok
two three four
[rc@localhost work]$ cat text | grep -o -E "(\<\w+\>) (\<\w+\>) \1"
hello world hello
ok no ok
参考
- 知乎提问:你是如何学会正则表达式的