Skip to content

正则表达式

什么是正则表达式?

正则表达式(Regular Expression,简称 regex 或 regexp)是一种描述字符串模式的语法。它用于文本搜索、匹配、替换等操作,是 Linux 文本处理的核心技能。

正则表达式类型

Linux 中有两种主要的正则表达式:

类型说明支持工具
BRE基本正则表达式grep、sed
ERE扩展正则表达式egrep、grep -E、sed -E

主要区别

元字符BREERE
?\??
+\++
{}\{\}{}
()\(\)()
``|

基本元字符

字符匹配

元字符说明示例
.任意单个字符a.c 匹配 abc、adc
[]字符类[abc] 匹配 a、b、c
[^]否定字符类[^abc] 匹配非 a、b、c
\转义字符\. 匹配点号

字符类简写

元字符说明
[0-9]数字
[a-z]小写字母
[A-Z]大写字母
[a-zA-Z]所有字母
[a-zA-Z0-9]字母和数字

POSIX 字符类

字符类说明
[:alnum:]字母和数字
[:alpha:]字母
[:digit:]数字
[:lower:]小写字母
[:upper:]大写字母
[:space:]空白字符
[:punct:]标点符号
[:blank:]空格和 Tab
bash
# 使用 POSIX 字符类
$ grep '[[:digit:]]' file.txt
$ grep '[[:alpha:]]' file.txt

位置锚点

元字符说明示例
^行首^hello
$行尾world$
\b单词边界\bword\b
\B非单词边界\Bword\B
bash
# 匹配以 hello 开头的行
$ grep '^hello' file.txt

# 匹配以 world 结尾的行
$ grep 'world$' file.txt

# 匹配整行
$ grep '^hello world$' file.txt

# 匹配空行
$ grep '^$' file.txt

# 匹配完整单词
$ grep '\bword\b' file.txt

重复限定符

元字符说明示例
*零次或多次ab*c 匹配 ac、abc、abbc
+一次或多次ab+c 匹配 abc、abbc
?零次或一次ab?c 匹配 ac、abc
{n}正好 n 次a{3} 匹配 aaa
{n,}至少 n 次a{2,} 匹配 aa、aaa...
{n,m}n 到 m 次a{2,4} 匹配 aa、aaa、aaaa
bash
# 基本使用
$ grep 'ab*c' file.txt       # BRE
$ grep -E 'ab+c' file.txt    # ERE

# 指定次数
$ grep 'a\{3\}' file.txt     # BRE
$ grep -E 'a{3}' file.txt    # ERE

# 范围
$ grep -E 'a{2,4}' file.txt

分组和捕获

bash
# 分组
$ grep -E '(ab)+' file.txt    # 匹配 ab、abab、ababab

# 后向引用
$ grep -E '(.).\1' file.txt   # 匹配 aba、aca 等

# sed 中使用
$ sed 's/\(hello\) \(world\)/\2 \1/' file.txt
# ERE
$ sed -E 's/(hello) (world)/\2 \1/' file.txt

交替(或)

bash
# 使用 |
$ grep -E 'cat|dog' file.txt

# 与分组组合
$ grep -E '(red|blue) car' file.txt

常用模式示例

数字

bash
# 整数
[0-9]+
\d+

# 浮点数
[0-9]+\.[0-9]+

# 正负数
-?[0-9]+

字符串

bash
# 引号字符串
"[^"]*"
'[^']*'

# 任意单词
\b\w+\b

常见格式

bash
# Email
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}

# URL
https?://[^\s]+

# IP 地址(简化)
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

# 日期 YYYY-MM-DD
[0-9]{4}-[0-9]{2}-[0-9]{2}

# 时间 HH:MM:SS
[0-9]{2}:[0-9]{2}:[0-9]{2}

# 电话号码(中国手机)
1[3-9][0-9]{9}

grep 中使用正则

bash
# 基本正则
$ grep 'pattern' file.txt

# 扩展正则
$ grep -E 'pattern' file.txt
$ egrep 'pattern' file.txt

# Perl 正则
$ grep -P 'pattern' file.txt

# 只匹配完整单词
$ grep -w 'word' file.txt

# 显示匹配部分
$ grep -o 'pattern' file.txt

# 忽略大小写
$ grep -i 'pattern' file.txt

# 反向匹配
$ grep -v 'pattern' file.txt

实例

bash
# 查找包含数字的行
$ grep '[0-9]' file.txt

# 查找以字母开头的行
$ grep '^[a-zA-Z]' file.txt

# 查找 email 地址
$ grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt

# 查找 IP 地址
$ grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' file.txt

# 查找空行或只有空白的行
$ grep -E '^[[:space:]]*$' file.txt

sed 中使用正则

bash
# 基本替换
$ sed 's/old/new/g' file.txt

# 使用扩展正则
$ sed -E 's/pattern/replacement/g' file.txt

# 后向引用
$ sed 's/\([a-z]\+\) \([a-z]\+\)/\2 \1/' file.txt
$ sed -E 's/([a-z]+) ([a-z]+)/\2 \1/' file.txt

# 使用 & 引用整个匹配
$ sed 's/[0-9]\+/【&】/g' file.txt

实例

bash
# 删除 HTML 标签
$ sed 's/<[^>]*>//g' file.html

# 删除行首空白
$ sed 's/^[[:space:]]*//' file.txt

# 提取引号内容
$ sed -E 's/.*"([^"]*)".*/\1/' file.txt

# 格式化电话号码
$ sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1-\2-\3/' file.txt

awk 中使用正则

bash
# 模式匹配
$ awk '/pattern/' file.txt

# 字段匹配
$ awk '$1 ~ /pattern/' file.txt
$ awk '$1 !~ /pattern/' file.txt

# 使用正则分隔符
$ awk -F '[,:]' '{print $1}' file.txt

# gsub 替换
$ awk '{gsub(/pattern/, "replacement"); print}' file.txt

实例

bash
# 打印包含数字的行
$ awk '/[0-9]/' file.txt

# 打印第一列是数字的行
$ awk '$1 ~ /^[0-9]+$/' file.txt

# 提取 email
$ awk 'match($0, /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/) {print substr($0, RSTART, RLENGTH)}' file.txt

贪婪与非贪婪

默认情况下,正则表达式是贪婪的,会尽可能多地匹配。

bash
# 贪婪匹配
$ echo "aaa bbb ccc" | grep -oE 'a.*c'
aaa bbb ccc

# 非贪婪匹配(Perl 正则)
$ echo "aaa bbb ccc" | grep -oP 'a.*?c'
aaa bbb c

常见技巧

匹配不包含某字符串的行

bash
# 使用 -v 选项
$ grep -v 'pattern' file.txt

# 使用负向断言(Perl 正则)
$ grep -P '^(?!.*pattern)' file.txt

匹配多行

bash
# sed 中匹配多行
$ sed -n '/start/,/end/p' file.txt

# awk 中匹配多行
$ awk '/start/,/end/' file.txt

转义特殊字符

需要转义的特殊字符:. * + ? ^ $ [ ] { } ( ) | \

bash
# 匹配点号
$ grep '\.' file.txt

# 匹配方括号
$ grep '\[' file.txt

# 匹配反斜杠
$ grep '\\' file.txt

正则表达式测试工具

在线工具

  • regex101.com
  • regexr.com

命令行测试

bash
# 使用 grep 测试
$ echo "test string" | grep -E 'pattern'

# 使用 sed 测试
$ echo "test string" | sed -E 's/pattern/replacement/'

# 使用 awk 测试
$ echo "test string" | awk '/pattern/'

常见错误

1. 忘记转义

bash
# 错误:. 匹配任意字符
$ grep 'file.txt' file.txt

# 正确
$ grep 'file\.txt' file.txt

2. BRE 和 ERE 混淆

bash
# BRE 中 + 需要转义
$ grep 'a\+' file.txt

# ERE 中不需要
$ grep -E 'a+' file.txt

3. 贪婪匹配导致意外结果

bash
# 可能匹配过多
$ sed 's/<.*>//' file.html

# 使用否定字符类
$ sed 's/<[^>]*>//' file.html

小结

本章介绍了 Linux 正则表达式:

  • 元字符.*+?^$
  • 字符类[][^]、POSIX 类
  • 量词{n}{n,}{n,m}
  • 分组和引用()\1
  • 在各工具中使用:grep、sed、awk

正则表达式是一项需要练习的技能。从简单的模式开始,逐步掌握更复杂的用法。


上一章:文本处理工具

下一章:用户管理