
正则表达式小笔记
本文以 Linux 中的 GNU grep 为例,区分基本正则(BRE)与扩展正则(ERE)。其他工具的语法可能不同,正则不能到哪儿都一把梭。
正则表达式
需要注意
由普通字符(如大小写字母和数字)和元字符(存在特殊含义)组成。同一个符号在不同位置或正则类型中,含义可能不同。
默认区分大小写;需要忽略大小写时,可以使用 grep -i。元字符的语法含义与普通字母的大小写匹配是两回事。
基本正则表达式
| 元字符 | 作用 |
|---|---|
* |
前一个模式项重复0次或任意多次 如 z* 可匹配空字符串,所以 grep 'z*' 连不含 z 的行也会选中;匹配一个或多个 z 可写成 zz* |
. |
匹配除了换行符外任意一个字符 |
^ |
匹配行首 如: ^hello会匹配以hello开头的行 |
$ |
匹配行尾 如: hello$会匹配以hello结尾的行 |
[] |
匹配中括号中指定的任意一个字符,只匹配一个字符 如: [aoeiu]匹配任意一个元音字母[0-9]匹配任意一位数字[a-z][0-9]匹配一个小写字母和一位数字构成的两字符片段 |
[^] |
匹配除中括号的字符以外的任意一个字符 如: [^0-9]匹配任意一位非数字字符[^a-z]表示任意一位非小写字母 |
\ |
转义符 用于取消特殊符号的含义 |
\{n\} |
表示其前面的模式项恰好出现n次 如: [0-9]\{4\}匹配4位数字 ^1[3-9][0-9]\{9\}$ 检查常见的11位手机号格式(不验证号码是否真实存在) |
\{n,\} |
表示其前面的模式项出现不小于n次 例如: [0-9]\{2,\}表示两位及以上的数字 |
\{n,m\} |
表示其前面的模式项至少出现n次,最多出现m次 如: [a-z]\{6,8\}匹配6到8位的小写字母 |
扩展正则表达式
| 扩展元字符 | 作用 |
|---|---|
+ |
前一个模式项重复1次或任意多次 等价于{1,} 如 go+gle会匹配gogle、google或gooogle,当然如果 o有更多个,也能匹配 |
? |
前一个模式项重复0次或1次 等价于{0,1} 如 colou?r可以匹配colour或color |
![]() |
![]() |
( ) |
把括号中的表达式作为一个分组,便于对整个分组应用重复等操作 如 (dog)+会匹配dog、dogdog、dogdogdog等,因为被 ( )包含的字符会当成一个整体但`hello (world |
💡提示:补充:| 表示“或”,例如 dog|cat 匹配 dog 或 cat。ERE 还支持 {n}、{n,}、{n,m},不需要像 BRE 那样给花括号加反斜杠。
POSIX字符类
形如 [:…:],必须放在方括号表达式中使用,例如 [[:digit:]],不能直接写成 [:digit:]。下面使用完整写法;“相当于”一列按 LC_ALL=C 的常见字符范围理解,其他语言环境可能不同。
| POSIX 元字符 | 相当于 | 作用 |
|---|---|---|
[[:alnum:]] |
[0-9a-zA-Z] | 匹配字母和数字字符 |
[[:digit:]] |
[0-9] | 匹配数字字符 |
[[:alpha:]] |
[a-zA-Z] | 匹配字母字符 |
[[:lower:]] |
[a-z] | 匹配小写字母字符 |
[[:upper:]] |
[A-Z] | 匹配大写字母字符 |
[[:cntrl:]] |
匹配控制字符 | |
[[:graph:]] |
匹配可打印的非空白字符 | |
[[:space:]] |
空白字符 | 匹配空白字符 包括空格、制表符、换行符等 |
[[:blank:]] |
匹配空格和制表符字符 |
运算符优先级
正则的“优先级”指模式如何组合。以扩展正则为例,从高到低可以这样理解:
| 运算 | 说明 |
|---|---|
()、[] |
分组或字符集合先作为一个单元 |
*、+、?、{n,m} |
重复紧邻的前一个模式项 |
| 连接 | 相邻的模式按顺序匹配,例如 ab |
| |
选择多个分支,优先级最低 |
例如 m|food 匹配 m 或 food;(m|f)ood 才匹配 mood 或 food。(?:...)、(?=...) 属于其他正则语法,不适用于本文的 BRE/ERE。
匹配规则
基本模式匹配
模式是正则表达式最基本的元素,它是一组描述字符串特征的字符集,用于匹配字符串。
举例
^love匹配的是以love开头的字符串man$匹配的是以man结尾的字符串^bash$仅匹配bash这个字符串(精确匹配)- 匹配以制表符开头的行,可以在 Bash 中写
grep $'^\t' 文件名:这里由 Bash 将\t转换为真正的制表符,不是依赖 grep 解释\t。- 普通
grep逐行匹配,换行符不属于当前行的内容,不能照搬其他语言中的\n写法来跨行匹配。
- 普通
字符集合匹配
在程序中,要判断输入的电话号码、邮件地址等是否有效,用上述规则匹配显然是无法满足的;因此需要使用相应的字符模式的方法来描述,可以用方括号表达式描述字符集合。
举例
[a-z]匹配任意一个小写字母(此处按LC_ALL=C理解)[A-Z]匹配任意一个大写字母(此处按LC_ALL=C理解)grep -v '^$' 文件名排除空行;[^$]表示匹配一个不是字面量$的字符,不能当成排除空行的规则grep -E '^[+-]?[0-9]+(\.[0-9]+)?$' 文件名匹配可带正负号的整数或小数;此示例不包括.5、5.和科学计数法- POSIX字符类
- 正则表达式的组合应用
规则提取
grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,在文件中全局查找 指定的正则表达式,并打印所有包含该表达式的行。
如何理解
就像你在Windows中用记事本打开*.txt文件,通过Ctrl + F 在文本中查找某个字符串一样
孪生兄弟
grep支持基本正则表达式grep -E使用扩展正则表达式;旧命令名egrep已不推荐使用grep -F按固定字符串匹配,元字符也按字面量处理;旧命令名fgrep已不推荐使用,实际速度取决于模式和输入
使用说明
基本语法:grep [选项] [模式] 文件名
说明
- 选项:用于控制
grep的行为 - 模式:正则表达式模式
- 文件:要搜索的文件的列表
选项
| 选项 | 说明 |
|---|---|
| -i | 在搜索的时候忽略大小写 |
| -n | 显示结果所在行号 |
| -c | 统计匹配到的行数 注意:是匹配到的总行数,不是匹配到的次数 |
| -o | 只显示符合条件的字符串 即:每个符合条件的字符串单独显示一行 |
| -v | 输出不带匹配内容的行 反向查询(反向匹配) |
| -w | 匹配整个单词 匹配片段的两端必须是行边界或非单词字符;GNU grep 的单词字符包括字母、数字和下划线 |
-A 行数 |
在输出的时候包含结果所在行之后的指定行数 (A=After,之后) |
-B行数 |
在输出的时候包含结果所在行之前的指定行数 (B=Before,之前) |
-C 行数 |
在输出的时候包含结果所在行之前和之后的指定行数 (C=Context,上下文) |
| -e | 指定匹配模式;可重复使用,如 grep -e 'hello' -e 'shell' regex |
| -q | 静默模式,不输出任何信息 使用 echo $? 查看是否匹配;0 表示匹配到,1表示没有匹配到 |
| -E | 使用扩展正则表达式 相当于使用 egrep |
| –color=auto | 表示对匹配到的文本着色显示 也可直接用 --color选项 |
退出状态码
在grep操作完成后,其退出状态有特殊含义,如下所示。
找到匹配的表达式
0没找到匹配的表达式
1发生错误(例如找不到指定文件)时,GNU grep 返回
2
💡提示:-q 在找到匹配时可能返回 0,即使同时遇到了某些读取错误;它适合判断“是否匹配”,不能据此保证所有输入都读取成功。
基本用法
这里创建一段特定文本(命名为
regex),内容如下。
1
2
3
4
5
6
7
8 world hello
sayhello
hellosay
shell : root
class : shell
weclome to shell World
10,2023
saY shell
搜索包含shell的行
1 | grep "shell" regex |

搜索仅行首包含shell的行
1 | grep "^shell" regex |

搜索仅行尾包含shell的行
1 | grep "shell$" regex |

搜索仅包含shell的行
1 | grep "^shell$" regex |

搜索包含以 hello 开头的单词的行
1 | grep "\<hello" regex |

搜索包含以 hello 结尾的单词的行
1 | grep "hello\>" regex |

搜索包含完整单词 hello 的行
1 | grep "\<hello\>" regex |

搜索包含字符 y 的行(忽略大小写)
1 | grep -i "y" regex |

扩展说明
grep 默认使用基本正则表达式,grep -E 使用扩展正则表达式。下面的 \?、\+、\w、\W、\b、\<、\> 按 GNU grep 的语法理解,其中部分是 GNU 扩展,不能假设所有实现都支持。
正则最好用单引号包起来,减少 Shell 对 $ 等字符的展开;原来的简单截图示例保留双引号写法。
结合正则表达式
| 元字符 | 描述 |
|---|---|
[[:digit:]] 或 [0-9] |
匹配任意单个数字 |
[[:lower:]] 或 [a-z] |
匹配任意单个小写字母 |
[[:upper:]] 或 [A-Z] |
匹配任意单个大写字母 |
[[:alpha:]] 或 [a-zA-Z] |
匹配任意单个大写字母或小写字母 |
[[:alnum:]] 或 [0-9a-zA-Z] |
匹配任意单个字母或数字 |
结合特定模式
| 元字符 | 描述 |
|---|---|
^ |
锚定行首 |
$ |
锚定行尾 |
. |
匹配任意一个字符 |
* |
让前一个模式项重复零次或多次 |
\? |
匹配其前面的字符0次或者1次 |
\+ |
匹配其前面的字符1次或者多次 |
\{m\} |
匹配其前面的字符m次(\为转义符) |
\{m,n\} |
匹配其前面的字符至少m次,至多n次 |
[] |
匹配一个指定范围内的字符 而 [^]匹配指定范围外的任意单个字符 (排除) |
\< 或 \b |
\< 锚定词首,\b 匹配单词边界\<匹配对象\> 限定整个单词,不限定整行 |
\> 或 \b |
\> 锚定词尾,\b 匹配单词边界若需精确匹配整行,使用 ^匹配对象$ |
\(\) |
将多个字符当做一个整体进行处理 |
\1 |
模式从左侧起,第一个左括号及与之匹配的右括号之间模式匹配的内容 |
\2 |
模式从左侧起,第二个左括号及与之匹配的右括号之间模式匹配到的内容 |
\w |
匹配单个单词字符,即字母、数字或下划线,等价于 [[:alnum:]_] |
\W |
匹配单个非单词字符,等价于 [^[:alnum:]_] |
.* |
匹配任意长度的任意字符 |
💡提示
其中
\1、\2是后向引用,引用前面的分组括号中的模式所匹配到的字符在某行文本的检查中,如果使用
\(\)则分组括号中的模式匹配到的某内容可以被引用
小试一下
同样是 114514,查字面量与查正则,可不是一个路数:
1 | printf '%s\n' '114514' 'homo114514' '1145141919' | grep -E '^114514$' |
grep -c 统计的是行,grep -o 才会把同一行里的不同匹配分别输出。例如:
1 | printf '%s\n' '114514 114514' | grep -c '114514' |








