js 正则表达式

js正则表达式

'ajanuw'.replace(/a/g, 'x'); //"xjxnuw"

'ajanuw'.replace(new RegExp('a', 'g'), 'x'); //"xjxnuw"

修饰符 flags

g  全局匹配, `lastIndex`无效
i  忽略大小写  
m  多行搜索
u  启用对unicode的支持
s  让.能匹配到\n,就可以多行匹配
y 执行“粘性”搜索,匹配从目标字符串的当前位置开始,可以使用y标志,使用后将从`lastIndex`位置开始匹配

元字符

\t  水平制表符
\v  垂直制表符
\n  换行符
\r  回车符
\0 | 空字符
\f  换页符
\cX  控制字符 ctrl+x

字符类

[abc]  // a或b或c
[^abc]  //  不是a或b或c

范围内

[a-z]  //  a到z之间的全部
[a-zA-Z] // 大小写全部匹配
[0-9] // 数字范围

预定义类

.   除了回车换行之外的所有字符
\d  数字
\D  `非`数字
\s  空白符
\S  `非`空白符
\w  字母,数字,下划线
\W  `非`字母,数字,下划线
[^]  匹配任何字符,包括换行符。在多行字符串上非常有用

边界

^xx  从xx开始
xx$  从xx结束
\b  单词边界
\B  `非`单词边界

量词

字符 含义
? 出现0或1(最多出现一次)
+ 一次或多次(至少出现一次)
* 出现0次或多次(任意次)
{n} 出现n次
{n, m} 出现n次到m次
{n, } 至少出现n次

贪婪模式和非贪婪模式

匹配数字3-5次, 默认匹配最大值5
'123456'.replace(/\d{3,5}/, 'x'); //"x6"

在量词后面加上?号进入fei贪婪模式,匹配3次结束
'123456'.replace(/\d{3,5}?/, 'x'); //"x456"

分组( ) or |

'x1x1x1'.replace(/(x\d){2}/g, '-'); // 匹配x1连续出现两次

'x1x1x1'.replace(/x\d{2}/g, '-'); //匹配数字出现2次

反向引用

$`: 匹配部分的前一部分字符串
$&: 匹配的字符串
$': 还没有匹配的剩余字符串

 捕获分组内容 最多捕获7个
 'ajanuw'.replace(/(\w{3})(.*)/, '$2 $1')
 "nuw aja"
 
 ?: 可以忽略捕获,只需要分组
'ajanuw'.replace(/(\w{3})(?:.*)/, '$2 $1')
"$2 aja"


/(?<word>[a-z]+)!\k<word>$/.test('a!a') // true
/(?<word>[a-z]+)!\1$/.test('a!a') // 更上面一样true
/(?<word>[a-z]+)!\k<word>!\1$/.test('a!a!a') // 两种混写true

"hello world".replace(
  /(?<first>[a-z]+)\s(?<last>\w+)/, 
  (...args) => {
  let g = args[args.length - 1];
  // 没匹配上的话值为 undefined
  let { first, last } = g;
  console.log(g);
  console.log(first, last);
});

前瞻匹配(正相前瞻, 负相前瞻)

断言部分 不参与匹配

// 匹配 -后有单词的替换为_
// 正相前瞻
'text-danger-'.replace(/-(?=[a-zA-Z])/g, '_')  // text_danger-  最后一个-不符合要求

// 负相前瞻
'text-danger-'.replace(/-(?![a-zA-Z])/g, '_')  // text-danger_  更上面相反

Lookbehind断言 (于前瞻相反)

// 匹配 -前有单词的替换为_
'text-danger-'.replace(/(?<=[a-zA-Z])-/g, '_')  // "text_danger_"

// 匹配 -前没有有单词的替换为_
'text-danger--'.replace(/(?<![a-zA-Z])-/g, '_')  // "text-danger-_"

rep.lastIndex 当前表达式匹配内容的最后一个字符的下一个位置

rep.source 正则表达式的文本内容

表达式方法

  • test方法
test方法, 判断一个str里面是否含有正则匹配的参数
返回 false 或 true
会在内部调用rep.lastIndex, 对参数进行迭代
/\d{3}/.test('ajanuw'); //false 判断文本中连续出现3次的数字
  • exec方法
/((\w){3})/g.exec('ajanuw')
返回了一个数组
var res = ["aja", "aja", "a", index: 0, input: "ajanuw"]
res[0] 代表表达式所匹配的内容
res[1] 第一个 打组匹配的内容
res[2] 第2个 打组匹配的内容 以此类推
res[3] index代表在字符串中第几个开始匹配成功
res[4] input 匹配的文本
    
如果匹配失败 返回null
如果加上 g标志,会触发lastIndex
  • search方法
参数可以是 正则 或string
'ajanuw'.search(/\d/); -1
在字符串中查找, 找到返回index,没找到返回-1
忽略g标志
  • match方法
匹配成功返回数组, 否者返回 null
'a b c'.match('c')
["c", index: 4, input: "a b c"]
  • replace 替换
大概含有4各参数
1. 匹配到的字符串
2. 打组内容 g1, g2, g3不等
3. 匹配项在字符串中的index
4. 原字符串
'ajanuw'.replace(/\w{3}/, function(match){
  // match 匹配的结果 
  console.log(match);
  var args = Array.prototype.slice.call(arguments, 1); // 所有的打组
  var str = args.splice(args.length - 1, 1); // 获取元字符
  var index = args.splice(args.length - 1, 1) // 获取 index
  console.log(args);
})

命名捕获组

const RE_DATE = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31
console.log(year, month, day) // 1999 12 31 

console.log(matchObj) // ["1999-12-31", "1999", "12", "31"]

匹配回车换行

function f(s) {
  s = s.replace(/\\(\w)/g, "\\\\$1");
  console.log(s.split(/\r\n|\r|\n/));
}

获取当前匹配的字符串在第几行

function f(s) {
  s = s.replace(/\\(\w)/g, "\\\\$1");
  let startIndex = 0;
  let m = s.match(/hello/); // 匹配hello
  let startStr = s.substr(startIndex, m.index); // 斩出hello之前的字符串
  console.log(startStr.match(/\r\n|\r|\n/g).length); // 获取有多少个换行

  startIndex = m.index;
  let endIndex = startIndex + m[0].length;
}
posted @ 2017-12-06 23:35  Ajanuw  阅读(176)  评论(0)    收藏  举报