正则表达式

正则表达式是描述文本模式的语言。在 Shell 中,grep、sed、awk 等工具都支持正则表达式,用于搜索、匹配、替换文本。掌握正则表达式,是文本处理的核心技能。

基本正则表达式

基本正则表达式(BRE)是 POSIX 标准的一部分,大多数工具都支持。

元字符

元字符含义
.匹配任意单个字符
*匹配前一个字符 0 次或多次
^匹配行首
$匹配行尾
[]字符集合
[^]排除字符集合
\转义字符

示例

grep "a.c" file.txt
grep "ab*c" file.txt
grep "^hello" file.txt
grep "world$" file.txt
grep "[abc]" file.txt
grep "[0-9]" file.txt
grep "[^0-9]" file.txt

量词

在基本正则中,量词需要转义:

量词含义
\{n\}匹配前一个字符 n 次
\{n,\}匹配前一个字符至少 n 次
\{n,m\}匹配前一个字符 n 到 m 次
grep "a\{3\}" file.txt
grep "[0-9]\{3,5\}" file.txt

分组

基本正则中分组需要转义:

grep "\(ab\)\{2\}" file.txt

匹配 "abab"。

扩展正则表达式

扩展正则表达式(ERE)语法更简洁,不需要转义量词和分组。

启用扩展正则

grep -E "pattern" file.txt
egrep "pattern" file.txt
sed -r "s/pattern/replacement/" file.txt
awk '/pattern/' file.txt

扩展量词

量词含义
+匹配前一个字符 1 次或多次
?匹配前一个字符 0 次或 1 次
{n}匹配前一个字符 n 次
{n,}匹配前一个字符至少 n 次
{n,m}匹配前一个字符 n 到 m 次
grep -E "a+" file.txt
grep -E "a?" file.txt
grep -E "a{3}" file.txt
grep -E "a{2,5}" file.txt

分组和引用

grep -E "(ab)+" file.txt
grep -E "(a|b)" file.txt

| 表示或,(a|b) 匹配 a 或 b。

向后引用

\1\2 引用分组匹配的内容:

grep -E "(.)\1" file.txt

匹配连续两个相同的字符。

grep -E "([a-z]+) \1" file.txt

匹配重复的单词,如 "hello hello"。

常用模式

匹配邮箱

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 "([0-9]{1,3}\.){3}[0-9]{1,3}" file.txt

匹配日期

grep -E "[0-9]{4}-[0-9]{2}-[0-9]{2}" file.txt
grep -E "[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])" file.txt

匹配手机号

grep -E "1[3-9][0-9]{9}" file.txt

匹配 URL

grep -E "https?://[a-zA-Z0-9.-]+[/a-zA-Z0-9._%+-]*" file.txt

字符类

POSIX 定义了字符类,更易读:

字符类含义
[:alpha:]字母
[:digit:]数字
[:alnum:]字母和数字
[:space:]空白字符
[:punct:]标点符号
[:lower:]小写字母
[:upper:]大写字母
grep "[[:digit:]]" file.txt
grep "[[:alpha:]]" file.txt
grep "[[:space:]]" file.txt

在 sed 中使用正则

sed -r 's/[0-9]+/NUMBER/g' file.txt
sed -r 's/([a-z]+)/[\1]/g' file.txt
sed -r 's/^[[:space:]]+//' file.txt

在 awk 中使用正则

awk '/[0-9]+/' file.txt
awk '$1 ~ /^[a-z]+$/' file.txt
awk '$1 !~ /[0-9]/' file.txt
awk 'gsub(/[0-9]+/, "NUM")' file.txt

小结

  • 正则表达式用于描述文本模式
  • 基本正则需要转义量词,扩展正则不需要
  • . 匹配任意字符,* 匹配 0 次或多次
  • [] 字符集合,^ 行首,$ 行尾
  • + 匹配 1 次或多次,? 匹配 0 次或 1 次
  • () 分组,| 或,\1 向后引用