RegExp

# RegExp

# y 字符

连续匹配

const s = 'aaa_aa_a'
const r1 = /a+/g // 全局匹配
const r2 = /a+/y // 连续匹配 sticky

console.log(r1.exce(s)) // aaa
console.log(r2.exce(s)) // aaa

console.log(r1.exce(s)) // aa
console.log(r2.exce(s)) // null

# u 字符

匹配 unicode 码时,添加 u 字符

let s = '𠮷'
let s2 = '\uD842\uDFB7'

/^\uD842/.test(s2) // false
/^\uD842/u.test(s2) // true

/^.$/.test(s) // false
/^.$/u.test(s) // true

/\u{20BB7}/.test(s) // false
/\u{20BB7}/u.test(s) // true
/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true

# s 字符

// ES9 新增
// 正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。
// 一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;
// 另一个是行终止符(line terminator character)。

// 所谓行终止符,就是该字符表示一行的终结。以下四个字符属于“行终止符”。
// U+000A 换行符(\n)
// U+000D 回车符(\r)
// U+2028 行分隔符(line separator)
// U+2029 段分隔符(paragraph separator)

/foo.bar/.test('foo\nbar') // . 无法匹配 \n
// false

/foo.bar/s.test('foo\nbar') // 添加s修饰符后 true

const re = /foo.bar/s;

re.dotAll // true dotAll 判断是否有 s 修饰符
re.flags // 's'  flags 获取所有修饰符

# 后行断言

const str = 'hello world'

// 先行断言
str.match(/hello(?=\sworld)/); // 匹配到 hello 时,判断后面是不是 \sworld

// 后行断言
str.match(/(?<=hello\s)world/); // 匹配到 world 后,判断前面是不是 hello\s

# 常用方法

# test()

// test()  方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false
var reg = /(\d{4})-(\d{2})-(\d{2})/;
var dateStr = '2018-04-18';
reg.test(dateStr);  // true

# replace()

// replace() 字符串替换
var txt = str.replace(/microsoft/i,"Runoob");  // replace() 方法使用正则表达式
var txt = str.replace("Microsoft","Runoob");   // replace() 方法使用字符串
// search() 方法 。用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置
var str = "Visit Runoob!";
var n = str.search(/Runoob/i); // 6

# match()

// match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置
var str="Hello world!"
document.write(str.match("world") + "<br />")       // world
document.write(str.match("World") + "<br />")       // null
document.write(str.match("worlld") + "<br />")      // null
document.write(str.match("world!"))                 // world!

var str="1 plus 2 equal 3"
document.write(str.match(/\d+/g))         // 1,2,3

# exec()

// exec()方法:和match方法一样,搜索符合规则的内容,并返回内容,格式为数组。
var testStr = "now test001 test002";
var re = /test(\d+)/; //只匹配一次
var r = "";
var r = re.exec(testStr)
console.log(r);// test001 001 返回匹配结果,以及子项
console.log(r.length); // 2  返回内容的长度
console.log(r.input); // now test001 test002  代表每次匹配成功的字符串
console.log(r[0]);  // test001
console.log(r[1]);  // 001  代表每次匹配成功字符串中的第一个子项 (\d+)
console.log(r.index );  // 4  每次匹配成功的字符串中的第一个字符的位置

# 常用正则校验规则

// 手机号
export const mobile = /^0?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$/

// 电子邮箱
export const email = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/

// 密码【6-20位 包括特殊字符】
export const password = /^[A-Za-z0-9!#$%^&*.~,]{6,20}$/

// 正整数【不包含0】
export const integer = /^[1-9]\d*$/

// 金钱
export const money = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/

// 纳税识别号
export const TINumber = /^[A-Za-z0-9]+$/

// 身份证
export const IDCard = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/

// 账户名称【汉字、字母、数字、“-”、“_”的组合】以其开头并且匹配一个或任意多个
export const userName = /^[A-Za-z0-9_\-\u4e00-\u9fa5]+$/

// URL
export const URL = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/

// 固话
export const TEL = /0\d{2,3}-\d{7,8}/

// 密码强度校验
export const pPattern = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/

//车牌号正则
export const cPattern = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/;

# 其他

# 正则题

// 题目要求:
// 使用一个方法来扩展字典,该方法返回与模式匹配的单词列表。这个模式可以包含字母(小写)和占位符("?")。占位符只代表一个任意的字母,比如:

const fruits = new Dictionary(['banana', 'apple', 'papaya', 'cherry']);
fruits.getMatchingWords('lemon');     // must return []
fruits.getMatchingWords('cherr??');   // must return []
fruits.getMatchingWords('?a?a?a');    // must return ['banana', 'papaya']
fruits.getMatchingWords('??????');    // must return ['banana', 'papaya', 'cherry']

// 补充说明:
// (1)单词和模式都是小写
// (2)返回单词的顺序无关紧要

// 上面这道题目是典型的 正则表达式应用题,考察的知识点是2个:
// (1)使用 RegExp 对象 动态创建正则表达式
// (2)使用 /./ 匹配一个任意字符

// 字典构造器
function Dictionary(words) {
  this.words = words;
}
// 原型里拓展解法
Dictionary.prototype.getMatchingWords = function(pattern) {
  let res = []
  const reg = new RegExp("^" + pattern.replace(/\?/g, '.') + "$")  // 创建正则表达式
  for (let x of this.words) {
    if (reg.test(x)) res.push(x)
  }
  return res
}