360前端星计划--正则的三个应用场景

正则表达式的创建和使用

创建正则表达式的两种方式

01 使用正则表达式字面量

const reg = /[a-z]\d+[a-z]/i;

优点

  • 简单方便
  • 不需要考虑二次转义

缺点

  • 子内容无法重复使用
  • 过长的正则导致可读性差

02 使用 RegExp 构造函数

const alphabet = '[a-z]';
const reg = new RegExp(`${alphabet}\\d+${alphabet}`, 'i');

优点

  • 子内容可以重复使用
  • 可以通过控制子内容的粒度提高可读性

缺点

  • 二次转义的问题非常容易导致 bug
const reg = new RegExp(`\d+`);
reg.test('1'); // false
reg.test('ddd'); // true

正则表达式的常见用法

01 RegExp.prototype.test()

const reg = /[a-z]\d+[a-z]/i;

reg.test('a1a'); // true
reg.test('1a1'); // false
reg.test(Symbol('a1a')); // TypeError

输入

  要求输入字符串,如果输入的不是字符串类型,会尝试进行类型转换,转换失败会抛出 TypeError

输出

  true 或者 false,表示匹配成功或失败

02 RegExp.prototype.source  和 RegExp.prototype.flags

const reg = /[a-z]\d+[a-z]/ig;

reg.source; // "[a-z]\d+[a-z]"
reg.flags; // "gi"

get RegExp.prototype.source

  返回当前正则表达式的模式文本的字符串

get RegExp.prototype.flags

  es2015新增,返回当前正则表达式的修饰符的字符串,会对修饰符按照字母升序进行排序(gimsuy)

03 RegExp.prototype.exec() 和 String.prototype.match()

输入

RegExp.prototype.exec 要求输入字符串,遇到非字符串类型会尝试转换

String.prototype.match 要求输入正则表达式,遇到其它类型会先尝试转成字符串,再以字符串为 source 创建正则表达式

输出

匹配成功,返回匹配结果

匹配失败,返回 null

const reg = /(a)/g;

reg.exec('a1a'); // ["a", "a", index: 0, input: "a1a", groups: undefined]
'a1a'.match(reg); // ["a", "a"]

当正则表达式含有 g 修饰符时,RegExp.prototype.exec 每次只返回一个匹配结果,数据格式和不含 g 修饰符相同。

String.prototype.match 会返回所有的匹配结果,数据格式会变为字符串数组。

由于 String.prototype.match 返回的数据格式不固定,因此大多数情况都建议使用 RegExp.prototype.exec

04 RegExp.prototype.lastIndex

const reg = /(a)/g;
const str = 'a1a';

reg.lastIndex; // 0
reg.exec('a1a'); // ["a", "a", index: 0, input: "a1a", groups: undefined]
reg.lastIndex; // 1
reg.exec('a1a'); // ["a", "a", index: 2, input: "a1a", groups: undefined]
reg.lastIndex; // 3
reg.exec('a1a'); // null
reg.lastIndex; // 0

当前正则表达式最后一次匹配成功的结束位置(也就是下一次匹配的开始位置)

注意:lastIndex 不会自己重置,只有当上一次匹配失败才会重置为 0 ,因此,当你需要反复使用同一个正则表达式的时候,请在每次匹配新的字符串之前重置 lastIndex!

05 String.prototype.replace()、String.prototype.search()、String.prototype.split()

'a1a'.replace(/a/, 'b'); // 'b1a'
'a1a'.replace(/a/g, 'b'); // 'b1b'

'a1a'.search(/a/); // 0
'a1a'.search(/a/g); // 0

'a1a'.split(/a/); // ["", "1", ""]
'a1a'.split(/a/g); // ["", "1", ""]

场景一:正则与数值

数值判断不简单

01 /[0-9]+/

[]

字符集,使用连字符 - 表示指定的字符范围,如果想要匹配连字符,需要挨着方括号放置,或进行转义

0-9 表示匹配从 0 到 9 的数字字符,常用的还有 a-z 匹配小写字母,\u4e00-\u9fa5 匹配汉字等

如果只是匹配数字,还可以使用字符集缩写 \d

+

限定符,匹配一个或多个

这个正则的缺点

不是全字符匹配,存在误判,如 /[0-9]+/.test('a1') === true

02 /^\d+$/

^

匹配字符串开始位置,当结合 m 修饰符时,匹配某一行开始位置

$

匹配字符串结束位置,当结合 m 修饰符时,匹配某一行结束位置

这个正则的缺点

不能匹配带符号的数值,如 +1,-2

不能匹配小数,如 3.14159

03 /^[+-]?\d+(\.\d+)?$/

()

圆括号内是一个子表达式,当圆括号不带任何修饰符时,表示同时创建一个捕获组

?

? 在正则中有多种含义,作为限定符时,表示匹配零到一个

\.

. 可以匹配除换行符之外的任意字符,当结合 s 修饰符时,可以匹配包括换行符在内的任意字符

当匹配小数点字符时需要转义

这个正则的缺点

不能匹配无整数部分的小数,如 .123

捕获组会带来额外的开销

04 /^[+-]?(?:\d*\.)?\d+$/

(?:)

(?:)意思
这个代表不捕获分组
比较(X)和(?:X),前者是捕获分组,后者不捕获,区别在于正则表达式匹配输入字符串之后所获得的匹配的(数)组当中没有(?:X)匹配的部分;
比如

var m = "abcabc".match(/(?:a)(b)(c)/)
//结果 ["abc", "b", "c"]
// m[0] 是/(?:a)(b)(c)/匹配到的整个字符串,这里包括了a
// m[1] 是捕获组1,即(b)匹配的子字符串substring or sub sequence
// m[2] 是捕获组2,即(c)匹配到的
如果这样

var m = "abcabc".match(/(a)(b)(c)/)
//结果 ["abc", "a", "b", "c"]

创建一个非捕获组

可参考 https://www.cnblogs.com/pmars/archive/2011/12/30/2307507.html

(捕获组的编号是按照“(”出现的顺序,从左到右,从1开始进行编号的。)

*

限定符,匹配零个或多个

这个正则的缺点

不能匹配无小数部分的数值,如 2.

不能匹配科学计数法,如 1e2、3e-1、-2.e+4

完整的数值正则怎么写?

01 完整的数值 token

https://drafts.csswg.org/css-syntax-3/#number-token-diagram

注意:这个 token 是 CSS 的 token,在 javascript 中,要多考虑一种情况

+'2.'; // 2
+'2.e1'; // 20

02 /^[+-]?(?:\d+\.?|\d*\.\d+)(?: e[+-]?\d+)?$/i

|

javascript 中,数值还可以如何表示?

答案稍后给出

用来创建分支,当位于圆括号内时,表示子表达式的分支条件,当位于圆括号外时,表示整个正则表达式的分支条件

i 修饰符

思考题:这个正则已经没有缺点了吗?

表示匹配时忽略大小写,在这个例子中用于匹配科学计数法的 e,去掉 i 修饰符需要把 e 改为 [eE]

用正则处理数值

01 数值的解析

function execNumberList(str) {
   // ……
}

console.log(execNumberList('1.0px .2px -3px +4e1px')); // [1, 0.2, -3, 40]
console.log(execNumberList('+1.0px -0.2px 3e-1px')); // [1, -0.2, 0.3]
console.log(execNumberList('1px 0')); // [1, 0]
console.log(execNumberList('-1e+1px')); // [-10]
const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

function execNumberList(str) {
    reg.lastIndex = 0;
    let exec = reg.exec(str);
    const result = [];
    while (exec) {
        result.push(parseFloat(exec[0]));
        exec = reg.exec(str);
    }
    return result;
}

console.log(execNumberList('1.0px .2px -3px +4e1px')); // [1, 0.2, -3, 40]
console.log(execNumberList('+1.0px -0.2px 3e-1px')); // [1, -0.2, 0.3]
console.log(execNumberList('1px 0')); // [1, 0]
console.log(execNumberList('-1e+1px')); // [-10]
const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

(?=expression)

正向肯定环视 / 顺序肯定环视 / 先行断言

用于匹配符合条件的位置

类似的语法还有:

(?!expression) 正向否定环视 / 顺序否定环视 / 先行否定断言

(?<=expression) 反向肯定环视 / 逆序肯定环视 / 后行断言,es2018 新增

(?<!expression) 反向否定环视 / 逆序否定环视 / 后行否定断言,es2018 新增

const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

g

修饰符,表示全局匹配,用于取出目标字符串中所有符合条件的结果

需要注意的点

  • 按照 CSS 规范,只有数值为 0 才可以省略单位,这种情况没有必要靠正则来过滤
  • 这个例子中只验证了 px 单位,实际还存在 pt、em、vw 等单位,并且没有考虑百分比的情况
  • 实际工作中,要根据需求追加处理逻辑

02 数值转货币格式

function formatCurrency(str) {
   // ……
}

console.log(formatCurrency('1')); // 1
console.log(formatCurrency('123')); // 123
console.log(formatCurrency('12345678')); // 12,345,678
const reg = /(\d)(?=(\d{3})+(,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$1,');
}

console.log(formatCurrency('1')); // 1
console.log(formatCurrency('123')); // 123
console.log(formatCurrency('12345678')); // 12,345,678

{n}

限定符,表示重复 n 次,n 必须是非负整数

类似的语法还有:

{n, m} 表示重复 n 到 m 次,n 和 m 都必须是非负整数,且 n <= m

{n,} 表示重复 n 次以上

$n

用于 replace 的字符串中,表示第 n 个捕获组,n 可以从 1 到 9

$& 表示本次完整的匹配,所以这段代码还可以改写为:

const reg = /\d(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$&,');
}

在 es2018 以上的环境,还可以使用反向环视

const reg = /(?<=\d)(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, ',');
}

其它注意事项

环视中的圆括号也会生成捕获组,所以都要采用 (?:) 的非捕获组形式

颜色有多少种表示方式

01 16进制表示法

color: #rrggbb;
color: #rgb;
color: #rrggbbaa;
color: #rgba;

对应的正则写法

const hex = '[0-9a-fA-F]';
const reg = new RegExp(`^(?:#${hex}{6}|#${hex}{8}|#${hex}{3,4})$`);

其它注意事项

  • 也可以使用 i 修饰符来匹配大小写,i 修饰符和 a-fA-F 要根据实际需求来做取舍
  • 还记得前面的问题吗?

02 rgb/rgba 表示法

color: rgb(r, g, b);
color: rgb(r%, g%, b%);
color: rgba(r, g, b, a);
color: rgba(r%, g%, b%, a);
color: rgba(r, g, b, a%);
color: rgba(r%, g%, b%, a%);

对应的正则写法

const num = '[+-]?(?:\\d*\\.)?\\d+(?:e[+-]?\\d+)?';
const comma = '\\s*,\\s*';
const reg = new RegExp(`rgba?\\(\\s*${num}(%?)(?:${comma}${num}\\1){2}(?:${comma}${num}%?)?\\s*\\)`);

\n

反向引用,表示引用第 n 个捕获组

由于 r/g/b 必须同时为数值或百分比,所以 %? 只需要捕获一次,用 \1 来引用

\s

字符集缩写,用于匹配空白

需要注意的点

  • 按照规范,rgb(r,g,b,a) 和 rgba(r,g,b) 也是合法的
  • r/g/b 的值应该是 0~255 的整数,但是溢出或小数并不会报错
  • 当捕获组内的内容是可选的时候,一定要把问号写在捕获组内
    如果可选内容的圆括号不可省略,如(a|b|c)?,应该多嵌套一层:((?:a|b|c)?)

03 其它

/* hsl & hsla */
color: hsl(h, s%, l%);
color: hsla(h, s%, l%, a);
color: hsla(h, s%, l%, a%);

/* keywords */
color: red;
color: blue;
/* …… */

更多的颜色表示方法:

https://www.w3.org/TR/css-color/

用正则处理颜色

01 16进制颜色的优化

function shortenColor(str) {
   // ……
}

console.log(shortenColor('#336600')); // '#360'
console.log(shortenColor('#19b955')); // '#19b955'
console.log(shortenColor('#33660000')); // '#3600'
const hex = '[0-9a-z]';
const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');
function shortenColor(str) {
    return str.replace(hexReg, '#$<r>$<g>$<b>$<a>');
}

console.log(shortenColor('#336600')); // '#360'
console.log(shortenColor('#19b955')); // '#19b955'
console.log(shortenColor('#33660000')); // '#3600'

(?<key>)

  • es2018 新增,具名捕获组
  • 反向引用时的语法为 \k<key>
  • 在 replace 中,使用 $<key> 来访问具名捕获组
  • 当应用 exec 时,具名捕获组可以通过 execResult.groups[key] 访问
const hex = '[0-9a-z]';
const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');

hexReg.exec('#33660000');
// ["#33660000", "3", "6", "0", "0", index: 0, input: "#33660000", groups: {r: "3", g: "6", b: "0", a: "0"}]

场景三:正则与URL

01 用正则解析 URL

https://www.rfc-editor.org/rfc/rfc3986.html#section-3

简单起见,scheme 我们只匹配 http 和 https ,忽略 userinfo 部分

02 解析 URL

function execURL(url) {
    // ……
}

console.log(execURL('https://www.360.cn'));
{
  protocol: 'http:',
  host: 'www.360.cn',
  hostname: 'www.360.cn',
  port: '',
  pathname: '',
  search: '',
  hash: ''
}
console.log(execURL('http://localhost:8080/?#'));
{
  protocol: 'http:',
  host: 'localhost:8080',
  hostname: 'localhost',
  port: '8080',
  pathname: '/',
  search: '?',
  hash: '#'
}
console.log(execURL('https://image.so.com/view?q=360&src=srp#id=9e17bd&sn=0'));
{
  protocol: 'https:',
  host: 'image.so.com',
  hostname: 'image.so.com',
  port: '',
  pathname: '/view',
  search: '?q=360&src=srp',
  hash: '#id=9e17bd&sn=0'
}
console.log(execURL('this is not a url'));
{
  protocol: '',
  host: '',
  hostname: '',
  port: '',
  pathname: '',
  search: '',
  hash: ''
}
const protocol = '(?<protocol>https?:)';
const host = '(?<host>(?<hostname>[^/#?:]+)(?::(?<port>\\d+))?)';
const path = '(?<pathname>(?:\\/[^/#?]+)*\\/?)';
const search = '(?<search>(?:\\?[^#]*)?)';
const hash = '(?<hash>(?:#.*)?)';
const reg = new RegExp(`^${protocol}\/\/${host}${path}${search}${hash}$`);
function execURL(url) {
    const result = reg.exec(url);
    if (result) {
        result.groups.port = result.groups.port || '';
        return result.groups;
    }
    return {
        protocol: '', host: '', hostname: '', port: '',
        pathname: '', search: '', hash: '',
    };
}

console.log(execURL('https://www.360.cn'));
console.log(execURL('http://localhost:8080/?#'));
console.log(execURL('https://image.so.com/view?q=360&src=srp#id=9e17bd&sn=0'));
console.log(execURL('this is not a url'));

注意事项

  • port 捕获组可能为 undefined
  • 要考虑解析失败的情形

用正则解析 search 和 hash

完整解析

function execUrlParams(str) {
    // ……
}

console.log(execUrlParams('#')); // { }
console.log(execUrlParams('##')); // { '#': '' }
console.log(execUrlParams('?q=360&src=srp')); // { q: '360', src: 'srp' }
console.log(execUrlParams('test=a=b=c&&==&a=')); // { test: 'a=b=c', '': '=', a: '' }
function execUrlParams(str) {
    str = str.replace(/^[#?&]/, '');
    const result = {};
    if (!str) {
        return result;
    }
    const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;
    let exec = reg.exec(str);
    while (exec) {
        result[exec[1]] = exec[2];
        exec = reg.exec(str);
    }
    return result;
}

console.log(execUrlParams('#')); // { }
console.log(execUrlParams('##')); // { '#': '' }
console.log(execUrlParams('?q=360&src=srp')); // { q: '360', src: 'srp' }
console.log(execUrlParams('test=a=b=c&&==&a=')); // { test: 'a=b=c', '': '=', a: '' }
const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;

*?

? 可以跟在任何限定符之后,表示非贪婪模式(注意:这个例子其实不太恰当,使用贪婪模式效果是一样的)

y

es6 新增,粘连修饰符,和 g 修饰符类似,也是全局匹配。区别在于:

  1. y 修饰符每次匹配的结果必须是连续的
  2. y 修饰符在 match 时只会返回第一个匹配结果
 if (!str) {
        return result;
    }

02 解析指定 key

这是一道课后作业题,交给大家自己来完成

function getUrlParam(str, key) {
    // ……
}

console.log(getUrlParam('?nothing', 'test')); // ''
console.log(getUrlParam('#a=1&aa=2&aaa=3', 'a')); // '1'
console.log(getUrlParam('&b=1&a=1&b=2', 'b')); // '2'
console.log(getUrlParam('a=1&b=2&c=&d', 'c')); // ''
console.log(getUrlParam('&d==', 'd')); // '='

注意事项

  • 存在多个重复的 key 时,要求只返回最后一条匹配的结果
  • 挑战1:解法不止一种,你可以写出尽可能多的解法吗?
  • 挑战2:可以写出尽可能短的正则表达式吗?

总结

怎样用好正则表达式?

  • 明确需求
  • 考虑全面
  • 反复测试

表达式全集

字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\\”匹配“\”而“\(”则匹配“(”。
^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
.匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?<=pattern)反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。
[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d匹配一个数字字符。等价于[0-9]。
\D匹配一个非数字字符。等价于[^0-9]。
\f匹配一个换页符。等价于\x0c和\cL。
\n匹配一个换行符。等价于\x0a和\cJ。
\r匹配一个回车符。等价于\x0d和\cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\t匹配一个制表符。等价于\x09和\cI。
\v匹配一个垂直制表符。等价于\x0b和\cK。
\w匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.
\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。

 

常用正则表达式

用户名/^[a-z0-9_-]{3,16}$/
密码/^[a-z0-9_-]{6,18}$/
十六进制值/^#?([a-f0-9]{6}|[a-f0-9]{3})$/
电子邮箱/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/
URL/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
IP 地址/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 标签/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/
删除代码\\注释(?<!http:|\S)//.*$
Unicode编码中的汉字范围/^[\u2E80-\u9FFF]+$/
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值