正则表达式

正则表达式起源于对形式语言(formal language)的数学研究,它趋向于极致而简洁的书写风格,所有的字符挤在一起,不仅难以阅读,而且在维护时也非常困难。Javascript正则表达式借鉴自Perl,它不支持注释和空白,且处在不同位置的相同字符都可能代表不同的意义。 但是我们为何又要使用它呢? 这主要是因为,相比等效的字符串处理,Javascript正则表达式有着明显的性能优势。

参考:https://en.wikipedia.org/wiki/Formal_language

下面通过例子来感受一下:

/**
 * 处理一个url串,并捕获其中的协议名、主机名(*)、端口号、路径名、查询条件和哈希值
 * 其中,除了主机名是捕获型分组外,其他的皆为非捕获型
 */
// 以为例
var url = 'http://www.jianshu.com:8080/u/101db3165437?user=JSoon#info';
// 处理后的url
var parsed = /^(?:([a-zA-Z]+):)?(\/{0,2})([a-zA-Z0-9\.\-]*)(?::([0-9]+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:\#(.*))?$/.exec(url);
// 在控制台打印
console.log(parsed);

结果如下图:


正则表达式_第1张图片
QQ截图20170108152821.png

首先来看parsedregexp.exec(string)返回一个结果数组,数组的第一项为该正则表达式的匹配结果,不计入分组。
参考:RegExp.prototype.exec()
parsed[1]开始直到parsed[7],则是正则表达式分组所匹配到的值。

正则表达式为两个正斜杠之间所夹的符号串/regexp/组成,在本例中,第一个/后的^表示以第一个分组所匹配的字符串开始,它像一个锚,只会匹配以次开头的字符串,否则返回null。最后一个/前的$表示这个字符串的结束,这就能确保匹配的精确性。


分组一:

// 协议名
(?:([a-zA-Z]+):)? // 匹配一段后边紧跟一个冒号的字符串。如果没有,则会返回undefined,因为+告诉了正则匹配器,必须得到至少一个英文字符
// 匹配结果
console.log(parsed[1]); // "http"

(?:)表示这是一个非捕获型分组,后面的?表明这是一个非贪婪性匹配?等同于{0,1}。表示如果整个字符串中都没有匹配到这个字符串,也不会影响匹配的进行。若去掉这个?,而字符串中又没有如http:之类的子串,那么正则匹配将立即结束,并返回null

其内部有一个捕获型分组([a-zA-Z]+)[a-zA-Z]是一个字符集,它指定了一组字符串,这里表示所有的大小写英文字母,后边的+表示贪婪性匹配,等同于{1,},即至少匹配一个英文字母。([a-zA-Z]+)后边的:表示这段英文字母后紧接着是一个冒号,如若不是,匹配也会失败。

分组二:

// 斜杠
(\/{0,2}) // 匹配0到2个连续的斜杠。如果没有斜杠,则会返回""空串
// 匹配结果
console.log(parsed[2]); // "//"

这个很好理解,在正则中,若想将斜杠之类的特殊字符按照字面量来匹配,则必须使用反斜杠前缀对其进行转义。这里一个小窍门是,如果你拿不准哪些特殊字符需要转义,一个保险的做法是,给任何特殊字符都添加一个反斜杠前缀来使其字面量化。注意反斜杠前缀并不能使字母或数字字面量化。

分组三:

// 主机名
([a-zA-Z0-9\.\-]*) // 匹配至少0次包含大小写英文字母,数字,点号和连字符
// 匹配结果
console.log(parsed[3]); // "www.jianshu.com"

.-被转义,将.转义是一种保险的做法,因为这里我并不确定它在字符集中是否代表其他含义;而将-转义的目的是因为连字符在字符集中表示范围,如[0-9]表示[0123456789]

分组四:

// 端口号
(?::([0-9]+))? // 匹配以冒号开始,以及之后的数字。如果没有,其中的捕获分组会返回undefined,因为+告诉了正则匹配器,必须得到至少一个数字
// 匹配结果
console.log(parsed[4]); // "8080"

分组五:

// 路径名
(?:\/([^?#]*))? // 匹配以斜杠开始,以及除?和#之外所有的字符
// 匹配结果
console.log(parsed[5]); // "u/101db3165437"

分组六:

// 查询条件
(?:\?([^#]*))? // 匹配以?开始,以及除#之外所有的字符
// 匹配结果
console.log(parsed[6]); // "user=JSoon"

分组七:

// 哈希值
(?:\#(.*))? // 匹配以#开始,除行结束符以外的所有字符
// 匹配结果
console.log(parsed[7]); // "info"

特别的,一个未被转移的.会匹配除行结束符\n\r以外的任何字符。

若还需要对匹配结果进行再匹配,则可以对结果再次进行正则处理,这里就不细说了。

当然,除了用正则表达式字面量来创建正则表达式外,还可以使用RegExp构造函数来实现。RegExp适用于需要动态生成正则表达式,而不是事先就明确正则条件的情况时使用。
参考:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp

可以处理正则表达式的方法:

regexp.exec // 返回匹配结果的数组
regexp.test // 返回true or false
string.match // 返回与regexp.exec相同
string.replace // 用正则对匹配结果进行替换,返回替换后的新字符串
string.search // 返回匹配到的字符串的第一个字符的位置,若匹配失败,则返回-1
string.split // 用正则匹配到的字符作为分割器,然后返回分割后的各个字符的数组

欢迎交流,完。

你可能感兴趣的:(正则表达式)