手记

Linux Shell编程(5) - 正则表达式

原文链接:https://segmentfault.com/a/1190000015117538?utm_source=index-hottest

一、正则表达式简介

1. 正则表达式是什么

正则表达式用于描述字符排列和匹配模式的一种语法规则。
它主要用于字符串的模式分割、匹配、查找及替换操作。

2. 正则表达式与通配符

/正则表达式通配符
匹配主体文件中的内容文件名
匹配规则包含匹配完全匹配
常用命令grep,awk,sedls,find,cp

3. 通配符

* :匹配任意0到多个字符
? :匹配任意一个字符
[] :匹配括号中的一个字符

* 匹配任意0到多个字符

  • 目录下有5个文件,1个子目录

[root/tmp/tmp]# ll总用量 0
-rw-r--r-- 1 root root  0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 a.conf
-rw-r--r-- 1 root root  0 5月  31 03:37 a.md
-rw-r--r-- 1 root root  0 5月  31 03:37 bbb.md
-rw-r--r-- 1 root root  0 5月  31 03:37 bc.ini
drwxr-xr-x 2 root root 58 5月  31 03:39 sh/
  • 列出目录下所有文件,包含子目录中的文件

[root/tmp/tmp]# ll *-rw-r--r-- 1 root root  0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 a.conf
-rw-r--r-- 1 root root  0 5月  31 03:37 a.md
-rw-r--r-- 1 root root  0 5月  31 03:37 bbb.md
-rw-r--r-- 1 root root  0 5月  31 03:37 bc.ini

sh:
总用量 0
-rw-r--r-- 1 root root 0 5月  31 03:39 asd.sh
-rw-r--r-- 1 root root 0 5月  31 03:38 qwe.sh
-rw-r--r-- 1 root root 0 5月  31 03:39 rty.sh
-rw-r--r-- 1 root root 0 5月  31 03:39 zxc.sh
  • 列出以 a 开头和以 sh 开头的文件

[root/tmp/tmp]# ll a*-rw-r--r-- 1 root root 0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root 0 5月  31 03:37 a.conf
-rw-r--r-- 1 root root 0 5月  31 03:37 a.md

[root/tmp/tmp]# ll sh*总用量 0
-rw-r--r-- 1 root root 0 5月  31 03:39 asd.sh
-rw-r--r-- 1 root root 0 5月  31 03:38 qwe.sh
-rw-r--r-- 1 root root 0 5月  31 03:39 rty.sh
-rw-r--r-- 1 root root 0 5月  31 03:39 zxc.sh
  • 因为通配符是完全匹配,所以 a*c 匹配不到文件,必须用 a*c*

[root/tmp/tmp]# ll a*cls: 无法访问a*b: 没有那个文件或目录

[root/tmp/tmp]# ll a*c*-rw-r--r-- 1 root root 0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root 0 5月  31 03:37 a.conf
  • 匹配字目录中的文件

[root/tmp/tmp]# ll s*a*ls: 无法访问s*a*: 没有那个文件或目录
[root/tmp/tmp]# ll s*/a*-rw-r--r-- 1 root root 0 5月  31 03:39 sh/asd.sh

? 匹配任意一个字符

[root/tmp/tmp]# ll总用量 0
-rw-r--r-- 1 root root  0 5月  31 03:59 aaa.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 aaa.md
-rw-r--r-- 1 root root  0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 bbb.md
-rw-r--r-- 1 root root  0 5月  31 03:37 cbc.ini
drwxr-xr-x 2 root root 58 5月  31 03:39 sh/

[root/tmp/tmp]# find . -name '?bc.ini'./abc.ini
./cbc.ini

[root/tmp/tmp]# find . -name '???.md'./bbb.md
./aaa.md

[root/tmp/tmp]# find . -name 'a??.ini'./abc.ini
./aaa.ini

[root/tmp/tmp]# find . -name 's?'./sh

[] 匹配括号中的一个字符

[root/tmp/tmp]# ll总用量 0
-rw-r--r-- 1 root root  0 5月  31 03:59 aaa.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 aaa.md
-rw-r--r-- 1 root root  0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root  0 5月  31 03:37 bbb.md
-rw-r--r-- 1 root root  0 5月  31 03:37 cbc.ini
drwxr-xr-x 2 root root 58 5月  31 03:39 sh/

[root/tmp/tmp]# ll [a-z]bc.ini-rw-r--r-- 1 root root 0 5月  31 03:37 abc.ini
-rw-r--r-- 1 root root 0 5月  31 03:37 cbc.ini

[root/tmp/tmp]# ll [ab]bc.ini-rw-r--r-- 1 root root 0 5月  31 03:37 abc.ini

二、基础正则表达式

元字符作用
*前一个字符匹配0次或任意多次
.匹配除了换行符以外的任意一个字符
^匹配行首。例如:^hello 会匹配以 hello 开头的行
$匹配行尾。例如:hello$ 会匹配以 hello 结尾的行
[]匹配括号中任意一个字符,只匹配一个字符。例如:
[aeiou]匹配任意一个元音字符
[0-9]匹配任意一个数字
[a-z]匹配任意一个小写字母
[^]取反,匹配括号中字符以外的任意一个字符。例如:
[^0-9]匹配任意一个非数字字符
[^a-z]匹配任意一个非小写字母字符
\转义符,用于取消特殊符号的含义。例如:\. 匹配符号 '.'
\{n\}表示其前面的字符恰好出现n次。
\{n,\}表示其前面的字符至少出现n次。
\{n,m\}表示其前面的字符至少出现n次,最多出现m次。

0. 测试用文档

使用 grep -n '[正则表达式]' [文件] 命令来输出匹配的行,并显示行号。
  • test.md

 1  a 2  aa 3  aaa 4  aaaa 5  aaaaa 6
 7  b 8  bb 9  bbb10  bbbb11  bbbbb1213  ab14  aab15  abcb16  abcde1718  said19  soid20  suud21  sooooood2223  02345624  122345625  12326  344527  425asdf28  dasd1234ff2930  3.141592631  hello world.3233  2018-05-3134  2017-02-223536  192.168.33.1037  255.255.255.25538  0.0.0.0

1. * 前一个字符匹配0次或任意多次

2. . 匹配除了换行符以外的任意一个字符

  • .* 匹配所有内容,包括空白行

  • s..d 匹配在 s 和 d 之间有两个字符的行

[root/tmp]# grep -n 's..d' test.md18:said19:soid20:suud
  • a.c 匹配在 a 和 c 之间有一个字符的行

[root/tmp]# grep -n 'a.c' test.md15:abcb16:abcde
  • a.*d 匹配在 a 和 d 之间有任意0到多个字符的行

[root/tmp]# grep -n 'a.*d' test.md16:abcde18:said27:425asdf28:dasd1234ff

3. ^ 匹配行首,$ 匹配行尾

  • ^s 匹配以 s 开头的行

[root/tmp]# grep -n '^s' test.md18:said19:soid20:suud21:sooooood
  • d$ 匹配以 d 结尾的行

[root/tmp]# grep -n 'd$' test.md18:said19:soid20:suud21:sooooood
  • ^$ 匹配所有空行

[root/tmp]# grep -n '^$' test.md6:12:17:22:29:32:35:

4. []|匹配括号中任意一个字符,只匹配一个字符。

  • s[aeiou]id 匹配 s 和 id 之间只有一个元音字母的行

[root/tmp]# grep -n 's[aeiou]id' test.md18:said19:soid
  • s[aeiou]*d 匹配 s 和 d 之间只有任意0个或多个元音字母的行

[root/tmp]# grep -n 's[aeiou]*d' test.md18:said19:soid20:suud21:sooooood27:425asdf28:dasd1234ff
  • [4-6] 匹配包含 4-6 之间的任意一个数字的行

[root/tmp]# grep -n '[4-6]' test.md23:02345624:122345626:344527:425asdf28:dasd1234ff30:3.141592633:2018-05-3136:192.168.33.1037:255.255.255.255
  • ^[c-z] 匹配以 c-z 之间的任意一个小写字母开头的行

[root/tmp]# grep -n '^[c-z]' test.md18:said19:soid20:suud21:sooooood28:dasd1234ff31:hello world.

5. [^] 取反,匹配括号中字符以外的任意一个字符

  • ^[^a-z] 匹配不以小写字母开头的行

[root/tmp]# grep -n '^[^a-z]' test.md23:02345624:122345625:12326:344527:425asdf30:3.141592633:2018-05-3134:2017-02-2236:192.168.33.1037:255.255.255.25538:0.0.0.0
  • [^a-z0-9] 匹配包含非数字和小写字母的行

[root/tmp]# grep -n '[^a-z0-9]' test.md30:3.141592631:hello world.33:2018-05-3134:2017-02-2236:192.168.33.1037:255.255.255.25538:0.0.0.0

6. \|转义符,用于取消特殊符号的含义

  • \. 匹配包含 '.' 的行

[root/tmp]# grep -n '\.' test.md30:3.141592631:hello world.36:192.168.33.1037:255.255.255.25538:0.0.0.0
  • \.$ 匹配以 '.' 结尾的行

[root/tmp]# grep -n '\.$' test.md31:hello world.

7. \{n\} 表示其前面的字符恰好出现n次

  • a\{3\} 匹配 a 连续出现 3 次的行

[root/tmp]# grep -n 'a\{3\}' test.md3:aaa4:aaaa5:aaaaa
  • [0-9]\{5\} 匹配包含连续5个数字的行

[root/tmp]# grep -n '[0-9]\{5\}' test.md23:02345624:122345630:3.1415926

8. \{n,\} 表示其前面的字符至少出现n次

  • a\{3,\} 匹配 a 至少连续出现 3 次的行

[root/tmp]# grep -n 'a\{3,\}' test.md3:aaa4:aaaa5:aaaaa
  • [0-9]\{5,\} 匹配包含至少连续5个数字的行

[root/tmp]# grep -n '[0-9]\{5,\}' test.md23:02345624:122345630:3.1415926

9. \{n,m\} 表示其前面的字符至少出现n次,最多出现m次。

  • s[a-z]\{2,5\}d 匹配 s 和 d 之间至少有2个字母,最多有5个字母的行

[root/tmp]# grep -n 's[a-z]\{2,5\}d' test.md18:said19:soid20:suud

三、几个实例

1. 匹配日期格式 'YYYY-MM-DD'

并非严格匹配日期格式,实际上是匹配 '9999-99-99'

[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}

[root/tmp]# grep -n '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}' test.md
33:2018-05-3134:2017-02-22

[0-9]\{4\}\(-[0-9]\{2\}\)\{2\}

[root/tmp]# grep -n '[0-9]\{4\}\(-[0-9]\{2\}\)\{2\}' test.md
33:2018-05-31
34:2017-02-22

2. 匹配IP地址

并非严格匹配IP地址,实际上是匹配 0.0.0.0 - 999.999.999.999,而实际IP地址只到 255.255.255.255

[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}

[root/tmp]# grep -n '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' test.md
36:192.168.33.10
37:255.255.255.255
38:0.0.0.0

[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}

[root/tmp]# grep -n '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' test.md
36:192.168.33.10
37:255.255.255.255
38:0.0.0.0


0人推荐
随时随地看视频
慕课网APP