js正则
修饰符
判断有哪些修饰符
/foo/gisu.flags // gisu
- m
如果有多行,包含\n,^和$也指每行开始和结尾
"java\nis fun java".match(/java$/ig) // 只匹配最后的 java ["java"]
"java\nis fun java".match(/java$/img) // 匹配两个 java ["java", "java"]
- i
ignore,不区分大小写
- g
模式匹配是全局的,匹配所有子串,否则只也只匹配一个子串
- y
和g修饰符一样都是全局匹配,sticky的意思
let s ='bbb_bb_b';
let a1 = /b+/g;
let a2 = /b+/y;//匹配了第一个,必须是紧跟着匹配上 隐含 ^ $
a1.exec(s) // ["bbb", index: 0, input: "bbb_bb_b", groups: undefined]
a1.exec(s) // ["bb", index: 4, input: "bbb_bb_b", groups: undefined]
a1.exec(s) // ["b", index: 7, input: "bbb_bb_b", groups: undefined]
a1.exec(s) // null
a2.exec(s) // ["bbb", index: 0, input: "bbb_bb_b", groups: undefined]
a2.exec(s) // null
- u
Unicode; 将模式视为Unicode序列点的序列
- s
dotAll 增强.
行终止符和.不匹配,
/foo.bar/.test('foo\nbar') // false
/foo.bar/.dotAll.test('fooabar') // true
/foo.bar/.dotAll // false
/foo.bar/s.dotAll // true
string 的正则方法
search:
找到返回第一个与之匹配的子串的起始位置,没有找到-1
search() 方法不执行全局匹配,它将忽略标志 g。它同时忽略 regexp 的 lastIndex 属性,并且总是从字符串的开始进行检索,这意味着它总是返回 stringObject 的第一个匹配的位置。
"Javascript".search(/script/i) // 4
replace
replace(regexp,replacement)用于检索和替换操作
regexp是正则表达式,replacement是要进行替换的字符串
- 如果有全局标志 g,那么将替换所有匹配的子串,否则它只替换第一个匹配上的子串。
- 不会改变原字符串,生成新的字符串
- 在每个匹配结果上使用replacement
replacement里面的$
$1-$99:分组匹配文本的序号
$&: 匹配的子串,整个
$` 匹配的子串左边,不包含子串
$' 匹配的子串右边,不包含子串
%% 美元符号
replacement 传函数
如果有多个匹配结果,多次调用函数
(matchStr,…,matchIndex,string)
matchStr:匹配字符串
…: 分组匹配的文本
matchIndex: 匹配的字符串的位置,
string: 字符串本身
返回值:替换文本的字符串
"javascript".replace(/(j)(a)/g, function (m,p1,p2){
return p2+p1;
}); // ajvascript
"javascript".replace(/(j)(a)/g, function (m,p1,p2){
return m;
});// javascript
"javascript".replace(/(j)(a)/g, function (m,p1,p2,p3,p4){
return _'+p3+'_'+p4;;
}); // _0_javascriptvascript
// ja 替换成_0_javascript
// 为什么呢,因为只有两个分组,p3代表匹配的字符串的位置是0
// p4代表字符串本身是javascript
match:
返回匹配结果组成的数组
和 exec 一样
var str = 'Hello world Hello';
str.match("world") //["world", index: 6, input: "hello world",groups:undefined]
str.match("World") //null
str.match("Hello") //["Hello", index: 0, input: "Hello world, Hello”]
str.match(/Hello/) //["Hello", index: 0, input: "Hello world, Hello”]
str.match(/Hello/g) //["Hello", "Hello”]
// 加了g,找到所有匹配子字符串
"javascript".match(/(j)(a)/)
0: "ja"
1: "j"
2: "a"
index: 0
input: "javascript"
groups: undefined
"javascript".match(/(j)(a)/g) // ["ja"]
groups:
// 原先是用
const t = '2019-11-11'.match(/(\d{4})-(\d{2})-(\d{2})/)
t(1)
t(2)
命名分组:
const t = '2019-11-11'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
t.groups.year
t.groups.month
matchAll
todo:matchAll
split
"123,456".split(",") // ["123","456"]
"123, 456,789".split(",") // ["123"," 456", "789"] 这样不对
"123, 456,789".split(/\s*,\s*/) // ["123","456", "789"] 这样有没有空格都可以分割
RegExp 对象
String的正则方法里面的 lastIndex都是0
正则的定义
字符串直接量和正则表达式
每次直接量返回新对象
var re1 = /a/
var re2 = /a/
re1 === re2 // false
如果传入一个字符串表述的正则表达式必须将””替换成”\”
var pattern = /hello\s/; // 正则表达式
var pattern = "hello\\s"; // 正则表达式
// 适合动态创建
var pattern = new RegExp(/hello\\s/);//字符串直接量
var pattern = new RegExp("hello\\s");//字符串直接量
构造函数
适合动态创建
构造函数的修改
es5
let regex = new RegExp(‘xyz’,’i’);// i忽略大小写
let regex2 = new RegExp(/xyz/i)
regex.test(‘xyz123’) // true
es6
let regex3 = new RegExp(/xyz/ig,’i’)//后面的修饰符i会覆盖前面的ig
//regex3.flags = i
属性
source: 只读的字符串,包含正则文本
global: 只读的布尔,是否有 G
ignoreCase: 是否有 i
lastIndex: 可读写,如果有 g,存储
exec
和 match 相似
没有修饰符 g
var reg = /hello\s/
reg.exec("hello hello ") // ["hello ", index: 0, input: "hello hello ", groups: undefined]
reg.lastIndex // 0
// 重复执行是一样的
// 匹配到第一个就结束
但是如果具有修饰符 g,match 返回数组,
但是 exec 还是返回没有 g 的数据解构,lastIndex
var reg = /hello\s/g
reg.exec("hello hello ") // ["hello ", index: 0, input: "hello hello ", groups: undefined]
reg.lastIndex // 6 匹配的子串的下一个位置
reg.exec("hello hello ") // 同一个正则第二次执行 从 lastIndex 开始["hello ", index: 6, input: "hello hello ", groups: undefined]
reg.lastIndex // 12
reg.exec("hello hello ") // null 重置 lastIndex 为0
reg.lastIndex // 0
所以在使用 reg 对象开始新的字符查找之前先将 lastIndex 置为0
使用 while 循环执行 exec
while(pattern.exec(text) !== null) {}
test
test 和 exec 等价,只是 test 只返回 true 和 false,同样都有 lastIndex
var reg = /hello\s/g
reg.test("hello hello ") // true
reg.lastIndex // 6 匹配的子串的下一个位置
reg.exec("hello hello ") // 同一个正则第二次执行 true
reg.lastIndex // 12
reg.exec("hello hello ") // false 重置 lastIndex 为0
reg.lastIndex // 0
最后一次如果检索失败,需要手动清空 lastIndex
现在每次创建正则直接量都是新的对象,会减少 lastIndex 的残流量
如何处理中文,如果是多个字节
Unicode 是「字符集」
UTF-8 是「编码规则」