js正则表达式迷你书(笔记)

一、字符匹配攻略

  • 横向模糊匹配(贪婪模式)
  • 纵向模糊匹配 [ ]
  • 字符组 [ ] : 匹配一个字符
  • 范围表示法:比如 [123456abcdefGHIJKLM],可以写成 [1-6a-fG-M]。用连字符 - 来省略和简写
  • 排除字符组 :例如 [^abc],表示是一个除 "a"、"b"、"c"之外的任意一个字 符。字符组的第一位放 ^(脱字符),表示求反的概念。
  • 常见的简写形式
字符组 具体含义
\d          表示 [0-9]。表示是一位数字。 记忆方式:其英文是 digit(数字)。
\D 表示 [^0-9]。表示除数字外的任意字符。本
\w 表示 [0-9a-zA-Z_]。表示数字、大小写字母和下划线。 记忆方式:w 是 word 的简写,也称单词字符。
\W 表示 [^0-9a-zA-Z_]。非单词字符。
\s 表示 [ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页符。记忆方式:s 是 space 的首字母,空白符的单词是 white space
\S 表示 [^ \t\v\n\r\f]。 非空白符。
. 表示 [^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符 除外。记忆方式:想想省略号 ... 中的每个点,都可以理解成占位符,表示任何类似的东西。
  • 常见的量词简写模式
量词 具体含义
{m,}    表示至少出现 m 次。
{m} 等价于 {m,m},表示出现 m 次。
? 等价于 {0,1},表示出现或者不出现。 记忆方式:问号的意思表示,有吗?
+ 等价于 {1,},表示出现至少一次。 记忆方式:加号是追加的意思,得先有一个,然后才考虑追加。
* 等价于 {0,},表示出现任意次,有可能不出现。 记忆方式:看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。
  • 贪婪匹配与惰性匹配

通过在量词后面加个问号就能实现惰性匹配

惰性量词 贪婪量词
{m,n}? {m,n}
{m,}? {m,}
?? ?
+? +
*? *

TIP : 对惰性匹配的记忆方式是:量词后面加个问号,问一问你知足了吗,你很贪婪吗?

  • 多选分支 : (p1|p2|p3),其中 p1、p2 和 p3 是子模式,用 |(管道符)分隔,表示其中任何之一

  • 案列分析

// 匹配时间
var regex = /^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/; 
console.log( regex.test("23:59") );
console.log( regex.test("02:07") );
console.log( regex.test("7:9") );
  // => true
  // => true
  // => true
// 匹配id
var regex = /id=".*?"/ // 一定要加惰性匹配,不然就是贪婪匹配,结果会错误的
var string = '<div id="container" class="main"></div>'; console.log(string.match(regex)[0]);
// => id="container"

或者如下

// 匹配id
var regex = /id="[^"]*"/  // 先匹配id="  然后匹配任何不是"的任意个字符 最后再匹配" 
var string = '<div id="container" class="main"></div>'; console.log(string.match(regex)[0]);
// => id="container"

二、位置匹配攻略

  • 关于位置的6个锚
含义
^ (脱字符)匹配开头,在多行匹配中匹配行开头
$ (美元符号)匹配结尾,在多行匹配中匹配行结尾
\b 单词边界,具体就是 \w 与 \W 之间的位置,也包括 \w 与 ^ 之间的位置,和 \w 与 $ 之间的位置
\B \b 的反面的意思,非单词边界
(?=p) 正向断言(预查) ;检查某个字符后面的字符是否满足某个规则,该规则不成为匹配结果,并且不成为捕获组
(?!p) 负向断言(预查); 检查某个字符后面的字符是否不满足某个规则,该规则不成为匹配结果,并且不成为捕获组
  • 案列分析
// 数字的千位分隔符表示法
var regex = /(?!^)(?=(\d{3})+$)/g;
var result = "12345678".replace(regex, ',') console.log(result);
// => "12,345,678"
result = "123456789".replace(regex, ','); console.log(result);
// => "123,456,789"

三、正则表达式括号的作用

  • 分组: var regex = /(ab)+/g; 其中括号是提供分组功能,使量词 + 作用于 "ab" 这个整体
  • 分支结构: 而在多选分支结构 (p1|p2) 中,此处括号的作用也是不言而喻的,提供了分支表达式的所有可能
  • 提取数据:可以从数组中获取,也可以从构造函数饿全局属性1至9来获取
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
console.log( string.match(regex) );
// => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"]

match 返回的一个数组,第一个元素是整体匹配结果,然后是各个分组(括号里)匹配的 NOTE 内容,然后是匹配下标,最后是输入的文本
另外也可以使用正则实例对象的 exec 方法

  • 替换
// 比如,想把 yyyy-mm-dd 格式,替换成 mm/dd/yyyy
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
var result = string.replace(regex, "$2/$3/$1"); console.log(result);
// => "06/12/2017"
  • 反向引用 :\捕获组编号
// 写一个正则支持匹配如下三种格式
// 2016-06-12
// 2016/06/12
// 2016.06.12
var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/; var string1 = "2017-06-12";
var string2 = "2017/06/12";
var string3 = "2017.06.12";
var string4 = "2016-06/12";
console.log( regex.test(string1) ); // true 
console.log( regex.test(string2) ); // true 
console.log( regex.test(string3) ); // true 
console.log( regex.test(string4) ); // false
  • 分组后面有量词: 分组后面有量词的话,分组最终捕获到的数据是最后一次的匹配
// 分组 (\d) 捕获的数据是 "5"
 var regex = /(\d)+/;
var string = "12345";
console.log( string.match(regex) );
// => ["12345", "5", index: 0, input: "12345"]
var regex = /(\d)+ \1/;
console.log( regex.test("12345 1") ); // => false
console.log( regex.test("12345 5") ); // => true
  • 非捕获符号: (?:)只想要括号最原始的功能, 不会成为捕获组
  • 案例分析
// 字符串 trim 方法模拟
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
console.log( trim(" foobar ") ); // => "foobar"
// 字符串 trim 方法模拟
function trim (str) {
return str.replace(/^\s*(.*?)\s*$/g, "$1");
}
console.log( trim(" foobar ") );
// => "foobar"
// 这里使用了惰性匹配 *?,不然也会匹配最后一个空格之前的所有空格的
// 非捕获组
// 将每个单词的首字母转换为大写
function titleize (str) {
return str.toLowerCase().replace(/(?:^|\s)\w/g, function (c) {
return c.toUpperCase(); });
}
console.log( titleize('my name is epeli') ); 
// => "My Name Is Epeli"

四、回溯法

简单总结就是,正因为有多种可能,所以要一个一个试。直到,要么到某一步时,整体匹配成功了;要么最后都试完后,发现整体匹配不成功。
贪婪量词“试”的策略是:买衣服砍价。价钱太高了,便宜点,不行,再便宜点。
惰性量词“试”的策略是:卖东西加价。给少了,再多给点行不,还有点少啊,再给点。
分支结构“试”的策略是:货比三家。这家不行,换一家吧,还不行,再换。

五、正则表达式的拆分

结构 说明
字面量          匹配一个具体字符,包括不用转义的和需要转义的。比如 a 匹配字符 "a", 又比如 \n 匹配换行符,又比如 . 匹配小数点。
字符组 匹配一个字符,可以是多种可能之一,比如 [0-9],表示匹配一个数字。也有 \d 的简写形式。 另外还有反义字符组,表示可以是除了特定字符之外任何一个字符,比如 [^0-9], 表示一个非数字字符,也有 \D 的简写形式。
量词     表示一个字符连续出现,比如 a{1,3} 表示 "a" 字符连续出现1到 3 次。 另外还有常见的简写形式,比如 a+ 表示 "a" 字符连续出现至少一次。
匹配一个位置,而不是字符。比如 ^ 匹配字符串的开头,又比如 \b 匹配单词边界, 又比如 (?=\d) 表示数字前面的位置。
分组 用括号表示一个整体,比如 (ab)+,表示 "ab" 两个字符连续出现多次, 也可以使用非捕获分组 (?:ab)+。
分支 多个子表达式多选一,比如 abc|bcd,表达式匹配 "abc" 或者 "bcd" 字符子串。 反向引用,比如 \2,表示引用第 2 个分组。
  • 操作符
操作符描述 操作符 优先级
转义符 \ 1
括号和方括号 (...)、(?:...)、(?=...)、(?!...)、[...] 2
量词限定符 {m}、{m,n}、{m,}、?、*、+ 3
位置和序列 ^、$、\元字符、一般字符 4
管道符(竖杠) 5
  • 所有结构里,用到的元字符总结如下:

^、$、.、*、+、?、|、\、/、(、)、[、]、{、}、=、!、:、- ,

六、replace 是很强大的

总体来说 replace 有两种使用形式,这是因为它的第二个参数,可以是字符串,也可以是函数。 当第二个参数是字符串时,如下的字符有特殊的含义:

属性 描述
1,2,...,$99 匹配第 1-99 个 分组里捕获的文本
$& 匹配到的子串文本
$` 匹配到的子串的左边文本
$' 匹配到的子串的右边文本
$$ 美元符号
  • 案例分析
// 把 "2,3,5",变成 "5=2+3"
var result = "2,3,5".replace(/(\d+),(\d+),(\d+)/, "$3=$1+$2"); 
console.log(result);
// => "5=2+3"
// 把 "2,3,5",变成 "222,333,555"
var result = "2,3,5".replace(/(\d+)/g, "$&$&$&"); 
console.log(result);
// => "222,333,555"
// 把 "2+3=5",变成 "2+3=2+3=5=5"
var result = "2+3=5".replace(/=/, "$&$`$&$'$&");
 console.log(result);
// => "2+3=2+3=5=5"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容