contents


1. 什么是正则表达式

1.1 正则表达式和通配符

  • 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed 等命令可以支持正则表达式。
  • 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp 这些命令不支持正则表达式,所以只能使用 shell 自己的通配符来进行匹配了。

可以在正则表达式中使用不同的特殊字符来定义特定的数据过滤模式。


数据流 正则表达式 过滤掉的数据 匹配的数据

root@jiaming-VirtualBox:/bin# ls -al d*
-rwxr-xr-x 1 root root 121432 125 2018 dash
-rwxr-xr-x 1 root root 100568 118 2018 date
-rwxr-xr-x 1 root root 76000 118 2018 dd
-rwxr-xr-x 1 root root 84776 118 2018 df
-rwxr-xr-x 1 root root 133792 118 2018 dir
-rwxr-xr-x 1 root root 72000 19 2020 dmesg
lrwxrwxrwx 1 root root 8 131 14:40 dnsdomainname -> hostname
lrwxrwxrwx 1 root root 8 131 14:40 domainname -> hostname
-rwxr-xr-x 1 root root 170520 122 2018 dumpkeys

1.2 正则表达式的类型

正则表达式不止有一种类型,编程语言的不同,Linux 实用工具的不同,主流应用的不同都会用不同的正则表达式类型。

在 Linux 中,有两种流行的正则表达式引擎:

  • POSIX 基础正则表达式引擎。(BRE模式)sed
  • POSIX 扩展正则表达式引擎。(ERE模式)gawk

大多数 Linux 工具都至少符合 BRE 引擎规范,但是有些工具(比如 sed 编辑器)只符合 BRE 引擎规范的子集。gawk 程序用 ERE 引擎来处理它的正则表达式。

元字符

作用

*

前一个字符匹配0次或任意多次。

.

匹配除了换行符外任意一个字符。

^

匹配行首。^hello,匹配hello开头的行。

$

匹配行尾。hello$,匹配hello结尾的行。

[]

匹配中括号中指定的任意一个字符,只匹配一个字符。 [aeiou]、[0-9]

[^]

匹配除了中括号内字符以外的任意一个字符。[^a-z]

\

转义符。

{n}

表示其前面的字符恰好出现n次。[0-9]{4} 匹配4位数字。

{n,}

表示其前面的字符出现不小于n次。[0-9]{2,} 匹配2位及以上的数字。

{n,m}

表示前面的字符至少出现n次,最多出现m次。

2. 定义 BRE 模式

2.1 纯文本

正则表达式都区分大小写,正则表达式不关系模式在数据流中的位置,也不关心模式出现了多少次。

$ echo "This is a test" | sed -n '/test/p'
This is a test
$ echo "This is a test" | gawk '/test/{print $0}'
This is a test

单词中间有两个空格的行匹配正则表达式模式,是用来查看文件中空格问题的好办法。

$ sed -n '/  /p' data.txt
This is a line with too many spaces.

2.2 特殊字符

特殊字符:

.*[]^${}\+?|() # 不能在文本模式中单独使用这些字符,如果要使用某个特殊字符作为文本字符,就必须转义

2.3 锚字符

jiaming@jiaming-VirtualBox:~/Documents/bin$ cat data.txt 
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this

2.3.1 锁定在行首

脱字符(^),定义从数据流中文本行的行首开始的模式,如果将其放到模式开头之外的其它位置,那么它就跟普通字符一样了。

jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/^this/p' data.txt 
this is another test line.

2.3.2 锁定在行尾

美元符($)定义了行尾锚点。

jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/line.$/p' data.txt 
This is a test line.
this is another test line.
jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/\.$/p' data.txt
This is a test line.
this is another test line.
A line that tests this feature.

2.3.3 组合锚点

只看特定文本:

sed -n '/^this is a test$/p' data.txt

输出空白行:

sed '/^$/d' data.txt

2.4 点号字符

jiaming@jiaming-VirtualBox:~/Documents/bin$ cat data.txt 
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this

特殊字符点号用来匹配除换行符之外的任意单个字符。

jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/.est/p' data.txt 
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this
jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/.ests/p' data.txt
A line that tests this feature.

2.5 字符组

jiaming@jiaming-VirtualBox:~/Documents/bin$ cat data.txt 
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this

使用方括号来定义一个字符串。

jiaming@jiaming-VirtualBox:~/Documents/bin$ sed -n '/t[eh]/p' data.txt
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this
echo "Yes" | sed -n '/[Yy][Ee][Ss]/p'

2.6 排除型字符组

只需要在字符组的开头加个脱字符。

sed -n '/[^ch]at/p' data.txt

2.7 区间

来制作一个过滤邮编的过滤器:

sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data.txt

2.8 特殊的字符组

处理定义自己的字符组外,BRE 还包含了一些特殊的字符组,可用来匹配特定类型的字符。


描述

[[:alpha:]]

匹配任意字母字符

[[:alnum:]]

匹配任意字母数字字符0~9、A~Z或a~z

[[:blank:]]

匹配空格或制表符

[[:digit:]]

匹配0-9之间的数字

[[:lower:]]

匹配小写字母

[[:upper:]]

匹配大写字母

[[:print:]]

匹配任意可打印字符

[[:punct:]]

匹配标点符号

[[:space:]]

匹配任意空白字符,空格,制表符,NL,FF,VT,CR

echo "abc123" | sed -n '/[[:digit:]]/p'
abc123

2.9 星号

在字符后面放置星号表面该字符必须在匹配模式的文本中出现 0 次或多次。

echo "ik" | sed -n '/ie*k/p'
ik

3. 扩展正则表达式

POSIX ERE 模式包括了一些可供 Linux 应用和工具使用的额外符号。gawk 能够识别 ERE 模式,但 sed 编辑器不能。

3.1 问号

问号表明前面的字符可以出现 0 次或 1 次,它不会匹配多次出现的字符。

echo "bet" | gawk '/bet?t/{print $0}'
echo "bet" | gawk '/b[ae]?t/{print $0}'

如果字符组中的字符出现了0次或1次,模式匹配就设立。但如果两个字符都出现了,或者其中一个字符出现了2次,模式匹配就不成立。

3.2 加号

加号表明前面的字符可以出现 1 次或多次,但必须至少出现 1 次,如果该字符没有出现,那么模式就不会匹配,同样可以使用字符组。

jiaming@jiaming-VirtualBox:~/Documents/bin$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
jiaming@jiaming-VirtualBox:~/Documents/bin$ echo "beet" | gawk '/be+t/{print $0}'
beet
jiaming@jiaming-VirtualBox:~/Documents/bin$ echo "bet" | gawk '/be+t/{print $0}'
bet
jiaming@jiaming-VirtualBox:~/Documents/bin$ echo "bt" | gawk '/be+t/{print $0}'
jiaming@jiaming-VirtualBox:~/Documents/bin$

3.3 花括号

ERE 中的花括号允许你为可重复的正则表达式指定一个上限。

  • m:正则表达式准确出现m次。
  • m,n:正则表达式至少出现m次,至多n次。

这个特性可以精确调整字符或字符集在模式中具体出现的次数。

$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
$ echo "beeet" | gawk --re-interval '/be{1,2}t/{print $0}'

3.4 管道符号

管道符号允许你检查数据流时,用逻辑或的方式指定正则表达式引擎用的两个或多个模式。

$ echo "The cat is asleep" | gawk '/cat|dog/{print $0}'

这个例子会在数据流中查找正则表达式 cat 或 dog。正则表达式和管道符号之间不能有空格。

$ echo "He has a hat." | gawk '/[ch]atdog/{print $0}'

3.5 表达式分组

正则表达式模式也可以用圆括号进行分组。当你将正则表达式模式分组时,该组会被视为一个标准字符。

$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'

该模式能够匹配完整的 Staturday 或缩写Sat。
模式 (c|b)a(b|t)会匹配第一组中字母的任意组合以及第二组中字母的任意组合。