首页 > Sysadmin > 正文

Linux 正则表达式编写指南与常用命令

huyuanwen 2026-11-03 Sysadmin

正则表达式是文本处理的核心工具,掌握 grep、sed、awk 的 regex 语法能大幅提升效率。

一、TL;DR:按场景选工具

  • 查找匹配行:grep -E 'pattern' file,ERE 语法最常用。
  • 替换文本:sed -E 's/old/new/g' file,捕获组用 \1 引用。
  • 字段处理:awk '/pattern/ {print $1}',内置 match() 和 gsub()。
  • BRE vs ERE:BRE 中 + ? {} () | 需加反斜杠转义;ERE 直接使用 [1]。
  • PCRE:grep -P 支持先行断言、命名分组等高级特性,但可移植性较差 [1]。

二、正则基础语法:元字符与量词

元字符 [3] [5]:

  • . 匹配任意单个字符(换行除外)。
  • * 匹配前一个元素 0 次或多次(贪婪)。
  • + 匹配前一个元素 1 次或多次(ERE/PCRE,BRE 中写 \+)。
  • ? 匹配前一个元素 0 次或 1 次(ERE/PCRE,BRE 中写 \?)。
  • {n} / {n,m} / {n,} 精确次数、范围、至少 n 次。
  • | 交替匹配(ERE/PCRE,BRE 中写 \|)。
  • () 分组(ERE/PCRE,BRE 中写 \(\))。
  • [] 字符类,[^] 取反。
  • ^ / $ 行首 / 行尾锚点。
  • \b / \B 单词边界 / 非单词边界(GNU 扩展)。
  • \w / \W / \d / \D / \s / \S(GNU 扩展)。

字符类 [3]:

  • [[:digit:]] 数字,[[:alpha:]] 字母,[[:space:]] 空白。
  • [[:alnum:]] 字母数字,[[:punct:]] 标点,[[:upper:]] 大写。
  • 范围 [a-z] [0-9],但 locale 影响排序,建议用字符类。

BRE 与 ERE 差异 [1]:

语法 BRE(默认 grep) ERE(grep -E)
量词 + \+ +
量词 ? \? ?
分组 \(\) ()
交替 `\ ` ` `
次数 \{n,m\} {n,m}

GNU grep 中 BRE 和 ERE 功能相同,只是符号写法不同。其他实现中 BRE 通常弱于 ERE。

三、grep:查找匹配行

grep -E 'pattern' file.txt
grep -P '(?<=prefix)pattern' file.txt
grep -i -n -v -w -o 'pattern' file.txt
  • -E 使用 ERE 语法 [1]。
  • -P 使用 PCRE 语法 [1],支持先行断言 (?=...)、后行断言 (?<=...)、命名分组 (?<name>...)。
  • -i 忽略大小写,-n 显示行号,-v 反向匹配,-w 全词匹配,-o 仅输出匹配部分。
  • -r 递归搜索目录,-l 仅列出文件名。

实测输出:

$ echo -e "test123\ntest\ntesting" > /tmp/test.txt
$ grep -E 'test[0-9]+' /tmp/test.txt
test123
$ grep -P '(?<=test)\d+' /tmp/test.txt
test123
$ grep -w 'test' /tmp/test.txt
test

四、sed:替换与转换

sed -E 's/old/new/g' file.txt
sed -E 's/(group1)(group2)/\2-\1/' file.txt
sed -n '/pattern/p' file.txt
  • s/old/new/ 替换第一个匹配 [2]。
  • g 标志全局替换所有匹配。
  • -E 使用 ERE 语法 [2],-r 是等价的旧写法。
  • \1 \2 引用捕获组 [2]。
  • -n 配合 p 命令仅输出匹配行。
  • d 删除匹配行,i 插入,a 追加。

实测输出:

$ echo "room 101 and room 202" | sed -E 's/[0-9]+/NUM/g'
room NUM and room NUM
$ echo "test123" | sed -E 's/(test)([0-9]+)/\1[\2]/'
test[123]

五、awk:字段处理与正则匹配

awk '/pattern/ {print $1}' file.txt
awk 'match($0, /regex/) {print substr($0, RSTART, RLENGTH)}' file.txt
awk '{gsub(/old/, "new"); print}' file.txt
  • /pattern/ 作为条件,匹配行执行后续动作 [4]。
  • match(s, r) 返回匹配位置,设置 RSTART 和 RLENGTH [4]。
  • gsub(r, s) 全局替换,sub(r, s) 替换第一个 [4]。
  • $0 是整行,$1 $2 是字段,FS 是字段分隔符。
  • ~ 匹配运算符:$1 ~ /pattern/。

实测输出:

$ echo "price=99.99 USD" | awk 'match($0, /[0-9]+\.[0-9]+/) {print substr($0, RSTART, RLENGTH)}'
99.99
$ echo -e "apple\nbanana" | awk '/^ap/ {print}'
apple

六、回滚、排错与局限性

排错速查

现象 原因 处理
grep: invalid option 旧版 grep 不支持 -P 改用 -E 或安装 PCRE 支持
BRE 中 + 不生效 BRE 默认不识别 + 加反斜杠 \+ 或改用 -E
sed 替换无效果 分隔符与内容冲突 换分隔符 s#old#new# [6]
awk match 返回 0 未匹配到 检查正则语法,awk 默认 ERE
中文匹配异常 locale 设置 export LC_ALL=C 或 LC_ALL=en_US.UTF-8

局限性

  • BRE/ERE 在不同实现(BSD grep、macOS sed)间存在差异,脚本应优先使用 POSIX 兼容语法或明确声明 GNU 依赖 [5]。
  • PCRE (grep -P) 依赖 libpcre2,部分最小化容器中不可用 [1]。
  • 正则表达式不擅长解析嵌套结构(如 HTML/XML),应使用专用解析器。
  • 复杂正则在大文件上性能较差,考虑用 awk 或 perl 优化。

实测记录

  • 环境:WSL2 Ubuntu 24.04,内核 5.15。
  • GNU grep 3.11:BRE/ERE/PCRE 三种语法均正常,-P 支持先行断言。
  • GNU sed 4.9:-E ERE 语法、捕获组 \1 正常。
  • GNU awk 5.2.1:pattern 匹配、match()、gsub() 均正常。
  • 测试数据:水果列表、数字字符串、价格字符串。

参考资料

文中主要命令已在 WSL Ubuntu(24.04)实测并核对其在 Debian 系与通用发行版的文档口径。