正则表达式的实用技巧
1. 正则表达式的平衡法则
- 只匹配期望的文本, 排除不期望的文本
- 必须易于控制和更紧
- 如果使用 NFA 引擎,必须保证效率(如果能匹配,必须很快地返回匹配结果,如果不能匹配,应该在尽可能短的时间内报告匹配失败)
2. 若干简单的例子
2.1 匹配连续行
SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c\
missing.c msg.c node.c re.c version.c
^\w+=.*(\\\n.*)* # .* 到匹配到 \\ 之后, 导致换行符 \\ 失效
^\w+=[^\n\\]*(\\\n[^\n\\]*)* # 使用排除型字符组,避免 .* 匹配换行符 \\, 但是会带来一个问题,反斜线不能出现行尾之外的地方
^\w+=([^\n\\]|\\.)* # 解决反斜线不能出现行尾之外的地方
2.2 匹配 IP 地址
^[0-9]+\.[0-9]+\.[0-9]$
^\d+\.\d+\.\d+\.\d+\$
^\d\d\d\.\d\d\d\.\d\d\d\.\d\d\d$
^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$
2.3 处理文件名
$ perl
$path = "/usr/local/bin/gcc";
$path =~ s{^.*/}{};
print "$path";
gcc
public static void main(String[] args) {
String path = "/usr/local/bin/gcc";
System.out.println(path.replaceFirst("^.*/", ""));
}
$path = "C:\\Program Files (x86)\\360";
$path =~ s/^.*\\//;
print "$path";
360
public static void main(String[] args) {
String path = "C:\\Program Files (x86)\\360";
System.out.println(path.replaceFirst("^.*\\\\", ""));
}
2.4 匹配对称的括号
\(.*\) 括号及括号内部的任何字符
\([^)]*\) 从一个开括号到最近的闭括号
\([^()]*\) 从一个开括号到最近的闭括号, 但是不容许其中包含开括号
2.5 防备不期望的匹配
s/-*/<HR>/ : 期望将每个连字符替换为<HR>, 但实际在在每一行添加<HR>, 因为 -* 中的 - 可以没有
-?[0-9]*\.?[0-9]* : 期望匹配所有数字, 包括浮点数; 但实际是 -.0、-aaa.333 也可以匹配
2.6 匹配分隔符之内的文本
- 匹配起始分隔符
- 匹配正文(结束分隔符之前的所有文本)
- 匹配结束分隔符
<a>www.baidu.com</a>
(?<=>)[^<]+ # 匹配 HTML 标签之间的内容
<code>
[^<]+?[^>] # 匹配标签内容
java android Linux
[^ ]+ # 以空格分隔
2.7 了解数据,做出假设
2.8 去除文本首尾的空白字符
^\s+ : 去除行首空白字符
\s+$ : 去除行尾空白字符
$ perl
$str = " regex ";
$str =~ s/^\s+//;
$str =~ s/\s+$//;
print "-$str-";
-regex-
3. HTML 相关范例
3.1 匹配 HTML Tag
<input name=dir value=">">
<code> text
java </pre>
<("[^"]*"|'[^']*'|[^'">])*>
< # 开始尖括号 "<"
( # 任意数量的...
"[^"]*" # 双引号字符串
| # 或者是
'[^']*' # 单引号字符串
| # 或者是
[^'">] # "其他文本"
)*
> # 结束尖括号 ">"
3.2 匹配 HTTP URL
m{^http://([^/:]+)(:(\d+))?(/.*)?$}i
3.3 验证主机名
^
(?i)
(?: [a-z0-9]\.|[a-z0-9][-a-z0-9]{0,61}[a-z0-9]\.)*
(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|coop|aero|[a-z][a-z])
$