JavaScript中一个经典的正则例子

学习知识的最好方法就是看例子.(个人观点) 因为书上总是会把概念和公式讲的晦涩难懂,才显得作者高大上.所以我总是喜欢 通过例子学习知识.每次写正则的时候总是喜欢查看例子学习如何使用,因为正则实在太耗脑细胞了,记不住,也没必要记住.学会 如何使用并在项目中熟练运用就好了,经常使用的话也就自然记住了.

JavaScript 语言精粹上面有个非常棒的学习例子,每次写正则的时候都会想起它.所以还是记一下分享给大家也方面我查询啦~

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var url = 'http://www.ora.com:80/goodparts?q#fragment';
var result = parse_url.exec(url);
var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];
var blanks = '     ';
var i;
for (i = 0; i < names.length; i += 1) {
  console.log(names[i] + ':' + blanks.substring(names[i].length), result[i]);
}
1
2
3
4
5
6
7
8
9

让我们分解 parse_url 的各个部分,看看它是如何工作的:

^
1

^字符表示此字符串的开始.它是一个锚,指引 exec 不要跳过那些不像 URL(non-URL-like)的前缀,只匹配那些从开头就像 URL 一样的字符串:

(?:([A-Za-z]+):)?
1

这个因子匹配一个协议名,但仅当它后面跟随一个:(冒号)的时候才匹配.(?:...)表示一个非捕获型分组(noncapturing group). 后缀 ? 表示这个分组是可选的. 问号表示重复 0 次或一次.(...)表示一个捕获型分组(capturing group).一个捕获型分组会复制它 所匹配的文本,并把其放到 result 数组里.每个捕获型分组都会被指定一个编号.第一个捕获型分组的编号是 1,所以该分组所匹配的文本副本 会出现在 result[1]中.[...]表示一个字符类,A-Za-z 这个字符类包含 26 个大写字母和 26 个小写字母.连字符( - )表示范围从 A 到 Z. 后缀 + 表示这个字符类会被匹配一次或者多次.这个组后面跟着字符:,它会按字面进行匹配:

(\/{0,3})
1

下一个因子是捕获型分组 2./表示该匹配/(斜扛).它是\(反斜杠)来进行转义,这样它就不会被错误地解释为这个正则表达式的结束符.后缀{0,3}表示 / 会被匹配 0 次,或者 1~3 次:

([0-9.\-A-Za-z]+)
1

下一个因子是捕获型分组 3.它会匹配一个主机名,由一个或多个数字、字母,以及 . 或 - 字符组成. - 会被转义为 \- 以防止与表示范围的连字符想混淆:

(?::(\d+))?
1

下一个可选的因子匹配端口号,它是由一个前置 : 加上一个或多个数字而组成的序列. \d 表示一个数字字符.一个或多个数字组成的数字串会被捕获型 分组 4 捕获:

(?:\/([^?#]*))?
1

接下来是另一个可选的分组.该分组以一个 / 开始. 之后的字符类[^?#]以一个 ^ 开始, 它表示这个类包含除了?和#之外的所有字符.*表示这个字符类 会被匹配 0 次或多次.

注意这里的处理是不严谨的.这个类匹配除?和#之外的所有字符,其中包括了行结束符、控制字符,以及其他大量不应在此被匹配的字符.大多数情况下,它会按照 我们的预期去做,但某些恶意文本可能会有渗透进来的风险.不严谨的正则表达式是一个常见的安全漏洞发源地.写不严谨的正则表达式比写严谨的正则表达式要容易得多.

(?:\?([^#]*))?
1

接下来,还有一个以一个 ? 开始的可选分组.它包含捕获型分组 6,这个分组包含 0 个或多个非#字符.

(?:#(.*))?
1

最后一个可选分组是以 # 开始的 .会匹配除行结束符以外的所有字符.

$
1

$表示这个字符串的结束.它保证在这个 URL 的尾部没有其他更多内容了.