Linux 正则表达式

  • 正则表达式作为一个 pattern,将 pattern 与要搜索的字符串进行匹配,以便查找一个或多个字符串。
  • 正则表达式,自成体系,由普通字符(例如字符 a 到 z)和元字符组成的文字模式。
    • 普通字符:没有显式指定为元字符的所有可打印和不可打印字符字符,包括所有大写和小写字母、所有数字、所有标点符号和其他一些符号。
    • 元字符:出了普通字符之外的字符。
  • 正则表达式,工具(vim、grep、less等)和程序语言(Perl、Python、C等)都使用正则表达式。

正则表达式分类:

  • 普通正则表达式
  • 扩展正则表示,支持更多的元字符。

环境准备

[laoma@shell ~]$ vim words
cat
category
acat
concatenate
dog

普通字符

[laoma@shell ~]$ cat words |grep 'cat'
cat
category
acat
concatenate

字符集

[…]

匹配 [...] 中的任意一个字符。

[laoma@shell ~]$ echo cbt >> words 
[laoma@shell ~]$ echo c1t >> words
[laoma@shell ~]$ cat words | grep 'c[ab]t'
cat
category
acat
concatenate
cbt

[a-z] [A-Z] [0-9]

  • [a-z],匹配所有小写字母。
  • [A-Z],匹配所有大写字母。
  • [0-9],匹配所有数字。
[laoma@shell ~]$ cat words | grep 'c[a-z]t'
cat
category
acat
concatenate
cbt

[laoma@shell ~]$ echo cCt >> words 
[laoma@shell ~]$ cat words | grep 'c[A-Z]t'
cCt

[laoma@shell ~]$ cat words | grep 'c[0-9]t'
c1t

[laoma@shell ~]$ cat words | grep 'c[a-z0-9]t'
cat
category
acat
concatenate
cbt
c1t

[laoma@shell ~]$ cat words | grep 'c[a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt

# 要想匹配-符号,将改符号写在第一个位置
[laoma@shell ~]$ echo c-t >> words 
[laoma@shell ~]$ cat words | grep 'c[-a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t

[^…]

匹配除了 [...] 中字符的所有字符。

[laoma@shell ~]$ cat words | grep 'c[^ab]t'
c1t

# ^放中间会被当做普通字符
[laoma@shell ~]$ cat words | grep 'c[a^b]t'
cat
category
acat
concatenate
cbt

.

匹配除换行符(\n\r)之外的任何单个字符,相等于\[^\n\r]

[laoma@shell ~]$ cat words | grep 'c.t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t

\

将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。

例如, ‘n’ 匹配字符 ‘n’。\n 匹配换行符。序列 \\ 匹配 \,而 \( 则匹配 (

[laoma@shell ~]$ echo c.t >> words 
[laoma@shell ~]$ cat words | grep 'c\.t'
c.t

# 匹配普通字符,虽然可以匹配,但强烈建议不要在前面加\
[laoma@shell ~]$ cat words | grep 'c\at'
cat
category
acat
concatenate

|

| 符号是扩展表达式中元字符,指明两项之间的一个选择。要匹配 |,请使用 \|

# 使用egrep或者grep -E 匹配
[laoma@shell ~]$ cat words | egrep 'cat|dog'
# 或者
[laoma@shell ~]$ cat words | grep -E 'cat|dog'
cat
category
acat
concatenate
dog
选项 描述
[[:digit:]] 数字: 0 1 2 3 4 5 6 7 8 9 等同于[0-9]
[[:xdigit:]] 十六进制数字: 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f等同于[0-9a-fA-F]
[[:lower:]] 小写字母:在 C 语言环境和ASCII字符编码中,对应于[a-z]
[[:upper:]] 大写字母:在 C 语言环境和ASCII字符编码中,对应于[A-Z]
[[:alpha:]] 字母字符:[[:lower:]和[[:upper:]];在C语言环境和ASCII字符编码中,等同于**[A-Za-z]**
[[:alnum:]] 字母数字字符:[:alpha:]和[:digit:];在C语言环境和ASCII字符编码中,等同于**[0-9A-Za-z]**
[[:blank:]]或者[[:space:]] 空白字符:在 C 语言环境中,它对应于制表符、换行符、垂直制表符、换页符、回车符和空格。
[[:punct:]] 标点符号:在C语言环境和ASCII字符编码中,它对应于!" # $ % &'()*+,-./:;<=>?@[]^_`{|}~
[[:print:]]或者 [[:graph:]] 可打印字符: [[:alnum:]]、[[:punct:]]。
[[:cntrl:]] 控制字符。在 ASCII中, 这些字符对应八进制代码000到037和 177 (DEL)。

非打印字符

终端中不显示的字符,例如换行符。

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。
\f 匹配一个换页符。等价于 \x0c\cL
\n 匹配一个换行符。等价于 \x0a\cJ
\r 匹配一个回车符。等价于 \x0d\cM
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]
\W 匹配任何非单词字符。等价于[^A-Za-z0-9_]
\t 匹配一个制表符。等价于 \x09\cI
\v 匹配一个垂直制表符。等价于 \x0b\cK

grep 命令支持\w\W\s\S

定位符

^

匹配行首位置。

[laoma@shell ~]$ cat words | grep '^cat'
cat
category

$

匹配行末位置。

[laoma@shell ~]$ cat words | grep 'cat$'
cat
acat

[laoma@shell ~]$ cat words | grep '^cat$'
cat

# 查询/etc/profile文件中有效行
[laoma@shell ~]$ cat /etc/profile | egrep -v '^#|^$'
# -v 取反,不显示匹配的内容

# 查看 /etc/ansible/ansible.cfg 中有哪些 section
[laoma@shell ~]$ cat /etc/ansible/ansible.cfg | egrep  '^\['

# 查看 /var/log/message Aug 19 14:01 到 Aug 19 14:06 时间段发生的事件
[laoma@shell ~]$ sudo cat /var/log/messages | egrep '^Aug 19 14:0[1-6]

\b

匹配一个单词边界。

[laoma@shell ~]$ echo hello cat >> words 
[laoma@shell ~]$ cat words | grep '\bcat'
cat
category
hello cat

[laoma@shell ~]$ cat words | grep 'cat\b'
cat
acat
hello cat

[laoma@shell ~]$ cat words | grep '\bcat\b'
cat
hello cat

\B

非单词边界匹配。

[laoma@shell ~]$ cat words | grep '\Bcat'
acat
concatenate

\< 和 \>

  • \< ,匹配一个单词左边界。
  • \>,匹配一个单词右边界。
[laoma@shell ~]$ cat words | grep '\<cat'
cat
category
hello cat

[laoma@shell ~]$ cat words | grep 'cat\>'
cat
acat
hello cat

限定次数

*

匹配前面的子表达式任意次数

[laoma@shell ~]$ echo dg >> words 
[laoma@shell ~]$ echo doog >> words 
[laoma@shell ~]$ cat words | grep 'do*g'
dog
dg
doog

+

+ 是扩展表达式元字符,匹配前面的子表达式一次以上次数

[laoma@shell ~]$ cat words | egrep 'do+g'
dog
doog

?

? 是扩展表达式元字符,匹配前面的子表达式一次以下次数

[laoma@shell ~]$ cat words | egrep 'do?g'
dog
dg

{n}

{} 是扩展表达式元字符,用于匹配特定次数。例如:{n},配置n次。

[laoma@shell ~]$ cat words | egrep 'do{2}g'
doog

{m,n}

{m,n},是扩展表达式元字符,用于匹配次数介于m-n之间。

[laoma@shell ~]$ echo dooog >> words
[laoma@shell ~]$ echo doooog >> words 

[laoma@shell ~]$ cat words | egrep 'do{2,3}g'
doog
dooog

{m,}

{m,},是扩展表达式元字符,匹配前面的子表达式m次以上次数

[laoma@shell ~]$ cat words | egrep 'do{2,}g'
doog
dooog
doooog

{,n}

{,n},是扩展表达式元字符,匹配前面的子表达式n次以下次数

[laoma@shell ~]$ cat words | egrep 'do{,3}g'
dog
doog
dg
dooog

()

标记一个子表达式。

[laoma@shell ~]$ echo dogdog >> words 
[laoma@shell ~]$ echo dogdogdog >> words 
[laoma@shell ~]$ echo dogdogdogdog >> words 

[laoma@shell ~]$ cat words | egrep '(dog){2,3}'
dogdog
dogdogdog
dogdogdogdog

[laoma@shell ~]$ cat words | egrep '(dog){2,}'
dogdog
dogdogdog
dogdogdogdog

**思考:**如何过滤出以下文件中所有有效IPv4地址?

0.0.0.0
1.1.1.1
11.11.11.111
111.111.111.111
999.9.9.9
01.1.1.1
10.0.0.0
0.1.1.1
266.1.1.1
248.1.1.1
256.1.1.1

参考答案

\b(([1-9][0-9]?)|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))(\.(([0-9])|([1-9][0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))){3}\b

'\b([1-9][0-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b'

反向引用

对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。

每个缓冲区都可以使用 \N 访问,其中 N 为一个标识特定缓冲区的一位或两位十进制数。

\N 这用引用方式称之为反向引用。

[laoma@shell ~]$ echo 'laoma laoniu laohu laoma laoniu laohu' | \
> egrep -o '(laoma) (laoniu).*\1'

# 过滤结果如下
laoma laoniu laohu laoma

[laoma@shell ~]$ echo 'Is is the cost of of gasoline going up up?' | \
> egrep -o '\b([a-z]+) \1\b' 
# 过滤结果如下
of of
up up

[laoma@shell ~]$ echo 'Is is the cost of of of gasoline going up up?' | egrep -o '(\b[a-z]+\b\s+)\1{1,}'
# 过滤结果如下
of of of

[laoma@shell ~]$ echo 'Is is the cost of  of of gasoline going up up?' | egrep -o '(\b[a-z]+\b\s+)\1{1,}'
# 过滤结果如下
of of

其他工具

vim

搜索和替换。

less

搜索。

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐