js正则

js 正则是 perl5正则的子集

修饰符

判断有哪些修饰符

  1. /foo/gisu.flags // gisu
  • m

如果有多行,包含\n,^和$也指每行开始和结尾

  1. "java\nis fun java".match(/java$/ig) // 只匹配最后的 java ["java"]
  2. "java\nis fun java".match(/java$/img) // 匹配两个 java ["java", "java"]
  • i

ignore,不区分大小写

  • g

模式匹配是全局的,匹配所有子串,否则只也只匹配一个子串

  • y

和g修饰符一样都是全局匹配,sticky的意思

  1. let s ='bbb_bb_b';
  2. let a1 = /b+/g;
  3. let a2 = /b+/y;//匹配了第一个,必须是紧跟着匹配上 隐含 ^ $
  4. a1.exec(s) // ["bbb", index: 0, input: "bbb_bb_b", groups: undefined]
  5. a1.exec(s) // ["bb", index: 4, input: "bbb_bb_b", groups: undefined]
  6. a1.exec(s) // ["b", index: 7, input: "bbb_bb_b", groups: undefined]
  7. a1.exec(s) // null
  8. a2.exec(s) // ["bbb", index: 0, input: "bbb_bb_b", groups: undefined]
  9. a2.exec(s) // null
  • u

Unicode; 将模式视为Unicode序列点的序列

  • s

dotAll 增强.
行终止符和.不匹配,

  1. /foo.bar/.test('foo\nbar') // false
  2. /foo.bar/.dotAll.test('fooabar') // true
  3. /foo.bar/.dotAll // false
  4. /foo.bar/s.dotAll // true

string 的正则方法

search:

找到返回第一个与之匹配的子串的起始位置,没有找到-1
search() 方法不执行全局匹配,它将忽略标志 g。它同时忽略 regexp 的 lastIndex 属性,并且总是从字符串的开始进行检索,这意味着它总是返回 stringObject 的第一个匹配的位置。

  1. "Javascript".search(/script/i) // 4

replace

replace(regexp,replacement)用于检索和替换操作
regexp是正则表达式,replacement是要进行替换的字符串

  • 如果有全局标志 g,那么将替换所有匹配的子串,否则它只替换第一个匹配上的子串。
  • 不会改变原字符串,生成新的字符串
  • 在每个匹配结果上使用replacement

    replacement里面的$

    1. $1-$99:分组匹配文本的序号
    2. $&: 匹配的子串,整个
    3. $` 匹配的子串左边,不包含子串
    4. $' 匹配的子串右边,不包含子串
    5. %% 美元符号

    replacement 传函数

    如果有多个匹配结果,多次调用函数
    (matchStr,…,matchIndex,string)
    matchStr:匹配字符串
    …: 分组匹配的文本
    matchIndex: 匹配的字符串的位置,
    string: 字符串本身

返回值:替换文本的字符串

  1. "javascript".replace(/(j)(a)/g, function (m,p1,p2){
  2. return p2+p1;
  3. }); // ajvascript
  4. "javascript".replace(/(j)(a)/g, function (m,p1,p2){
  5. return m;
  6. });// javascript
  7. "javascript".replace(/(j)(a)/g, function (m,p1,p2,p3,p4){
  8. return _'+p3+'_'+p4;;
  9. }); // _0_javascriptvascript
  10. // ja 替换成_0_javascript
  11. // 为什么呢,因为只有两个分组,p3代表匹配的字符串的位置是0
  12. // p4代表字符串本身是javascript

match:

返回匹配结果组成的数组
和 exec 一样

  1. var str = 'Hello world Hello';
  2. str.match("world") //["world", index: 6, input: "hello world",groups:undefined]
  3. str.match("World") //null
  4. str.match("Hello") //["Hello", index: 0, input: "Hello world, Hello”]
  5. str.match(/Hello/) //["Hello", index: 0, input: "Hello world, Hello”]
  6. str.match(/Hello/g) //["Hello", "Hello”]
  7. // 加了g,找到所有匹配子字符串
  8. "javascript".match(/(j)(a)/)
  9. 0: "ja"
  10. 1: "j"
  11. 2: "a"
  12. index: 0
  13. input: "javascript"
  14. groups: undefined
  15. "javascript".match(/(j)(a)/g) // ["ja"]

groups:
// 原先是用

  1. const t = '2019-11-11'.match(/(\d{4})-(\d{2})-(\d{2})/)
  2. t(1)
  3. t(2)

命名分组:

  1. const t = '2019-11-11'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
  2. t.groups.year
  3. t.groups.month

matchAll

todo:matchAll

split

  1. "123,456".split(",") // ["123","456"]
  2. "123, 456,789".split(",") // ["123"," 456", "789"] 这样不对
  3. "123, 456,789".split(/\s*,\s*/) // ["123","456", "789"] 这样有没有空格都可以分割

RegExp 对象

String的正则方法里面的 lastIndex都是0

正则的定义

字符串直接量和正则表达式

每次直接量返回新对象

  1. var re1 = /a/
  2. var re2 = /a/
  3. re1 === re2 // false

如果传入一个字符串表述的正则表达式必须将””替换成”\”

  1. var pattern = /hello\s/; // 正则表达式
  2. var pattern = "hello\\s"; // 正则表达式
  3. // 适合动态创建
  4. var pattern = new RegExp(/hello\\s/);//字符串直接量
  5. var pattern = new RegExp("hello\\s");//字符串直接量

构造函数

适合动态创建
构造函数的修改
es5

  1. let regex = new RegExp(‘xyz’,’i’);// i忽略大小写
  2. let regex2 = new RegExp(/xyz/i)
  3. regex.test(‘xyz123’) // true

es6

  1. let regex3 = new RegExp(/xyz/ig,’i’)//后面的修饰符i会覆盖前面的ig
  2. //regex3.flags = i

属性

source: 只读的字符串,包含正则文本
global: 只读的布尔,是否有 G
ignoreCase: 是否有 i
lastIndex: 可读写,如果有 g,存储

exec

和 match 相似

没有修饰符 g

  1. var reg = /hello\s/
  2. reg.exec("hello hello ") // ["hello ", index: 0, input: "hello hello ", groups: undefined]
  3. reg.lastIndex // 0
  4. // 重复执行是一样的
  5. // 匹配到第一个就结束

但是如果具有修饰符 g,match 返回数组,
但是 exec 还是返回没有 g 的数据解构,lastIndex

  1. var reg = /hello\s/g
  2. reg.exec("hello hello ") // ["hello ", index: 0, input: "hello hello ", groups: undefined]
  3. reg.lastIndex // 6 匹配的子串的下一个位置
  4. reg.exec("hello hello ") // 同一个正则第二次执行 从 lastIndex 开始["hello ", index: 6, input: "hello hello ", groups: undefined]
  5. reg.lastIndex // 12
  6. reg.exec("hello hello ") // null 重置 lastIndex 为0
  7. reg.lastIndex // 0

所以在使用 reg 对象开始新的字符查找之前先将 lastIndex 置为0

使用 while 循环执行 exec

  1. while(pattern.exec(text) !== null) {}

test

test 和 exec 等价,只是 test 只返回 true 和 false,同样都有 lastIndex

  1. var reg = /hello\s/g
  2. reg.test("hello hello ") // true
  3. reg.lastIndex // 6 匹配的子串的下一个位置
  4. reg.exec("hello hello ") // 同一个正则第二次执行 true
  5. reg.lastIndex // 12
  6. reg.exec("hello hello ") // false 重置 lastIndex 为0
  7. reg.lastIndex // 0

最后一次如果检索失败,需要手动清空 lastIndex
现在每次创建正则直接量都是新的对象,会减少 lastIndex 的残流量

如何处理中文,如果是多个字节

Unicode 是「字符集」
UTF-8 是「编码规则」