Perl 兼容正则表达式(PCRE)是 Perl scripting language 中所使用的正则表达式语法标准。这些正则表达式在 Linux 命令行工具(如 grep -P
)及其他编程语言和工具中也有广泛应用。以下是一些基础和进阶特性,帮你掌握和使用 PCRE。
基本概念
1. 元字符
.
: 匹配除了换行符之外的任何单个字符。^
: 匹配行的开始。$
: 匹配行的结尾。*
: 匹配前一个字符或子表达式零次或多次。+
: 匹配前一个字符或子表达式一次或多次。?
: 匹配前一个字符或子表达式零次或一次。{n,m}
: 匹配前一个字符或子表达式至少 n 次,但不超过 m 次。[]
: 匹配括号内的任意字符。|
: 选择匹配,表示“或”。- \K:重置之前的匹配,使得最终匹配结果从 \K 之后开始。
2. 转义字符
\
: 转义下一个字符,使其变为普通字符或启用特殊字符。
3. 字符类
\d
: 匹配任何一个数字,相当于[0-9]
。\D
: 匹配任何一个非数字字符。\w
: 匹配任何一个字母、数字或下划线字符,相当于[a-zA-Z0-9_]
。\W
: 匹配任何一个非字母、数字或下划线字符。\s
: 匹配任何一个空白符(空格、制表符等)。\S
: 匹配任何一个非空白符。
特性与操作
捕获和非捕获组
(...)
: 捕获组,可以匹配并记住。(?:...)
: 非捕获组,只进行匹配不记忆。
后向引用
\n
: 引用前面第 n 个捕获组,例如\1
。
零宽断言
- 正向先行断言:
(?=...)
,确保接下来的字符与…匹配。 - 负向先行断言:
(?!...)
,确保接下来的字符不与…匹配。 - 正向后行断言:
(?<=...)
,确保前面的字符与…匹配。 - 负向后行断言:
(?<!...)
,确保前面的字符不与…匹配。
贪婪与懒惰
*
、+
、?
、{n,}
等默认是贪婪的,匹配尽可能多的字符。*?
、+?
、??
、{n,}?
等是懒惰的,匹配尽可能少的字符。
示例
匹配 IP 地址
grep -oP '\b\d{1,3}(\.\d{1,3}){3}\b'
\b
: 单词边界,确保 IP 地址独立。\d{1,3}
: 匹配 1 到 3 个数字。(\.\d{1,3}){3}
: 匹配.
及 1 到 3 个数字的组合,重复 3 次。
提取 IP 地址
假设你有如下命令输出:
inet 192.168.134.128/24 brd 192.168.134.255 scope global dynamic noprefixroute ens160
使用 grep
结合 \K
来提取第一个 IP 地址的命令如下:
ip a show ens160 | grep -oP 'inet \K[\d.]+'
解释
'inet \K[\d.]+'
:inet
:匹配前缀inet
。\K
:重置匹配的开始位置,忽略掉之前的inet
。[\d.]+
:匹配一个或多个数字和点字符,表示 IP 地址。
其他示例
提取域名
假设你有一行包含 URL 的文本:
Access the site at https://www.example.com/page now.
使用 grep
来提取域名的命令如下:
echo "Access the site at https://www.example.com/page now." | grep -oP 'https://\K[^/]+'
解释
'https://\K[^/]+'
:https://
:匹配 URL 的前缀https://
。\K
:重置匹配的开始位置,忽略掉之前的https://
。[^/]+
:匹配非/
字符的一个或多个,表示域名部分。
使用场景
- 过滤文本:例如从大段文本中提取特定部分信息(如 IP 地址、域名、关键字段等)。
- 增强脚本:在自动化任务和脚本中进行复杂文本处理。
注意事项
\K
只能在 PCRE 模式下使用,因此确保使用grep -P
而不是grep
或其它不支持 PCRE 的工具。- 对于更复杂的匹配,可能需要结合其他正则表达式特性(如捕获组、断言等)来实现。
邮箱地址
grep -oP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
[a-zA-Z0-9._%+-]+
: 匹配邮箱用户名部分。@
: 匹配 @ 符号。[a-zA-Z0-9.-]+
: 匹配域名部分。\.[a-zA-Z]{2,}
: 匹配顶级域名部分。
实用工具
- 在线测试工具:如 regex101,支持 PCRE 语法,并且可以实时测试和调试你的正则表达式。
- 文本编辑工具:例如 Sublime Text 和 VSCode,都支持 PCRE 并提供强大的查找和替换功能。
实践
为了更好地掌握与应用 PCRE,多多练习和测试是最有效的方法。通过不断调整和优化你的正则表达式,会更好地理解它们的运行机制和应用场景。