目录
正则表达式是描述字符模式的对象,用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具。
RegExp(pattern,modifiers)
通过var reg=new RegExp(pattern,modifier)来创建对象,也可以通过var reg=/pattern/modifiers来创建正则表达式对象,其中pattern表示匹配的字符串模式,modifier为可选参数表示修饰符。正则表达式对象需要搭配方法使用。
修饰符
i
执行对大小写不敏感的匹配。
g
执行全局匹配(查找所有匹配而非找到第一个匹配后停止)。
m
执行多行匹配。
s
dotAll模式,该模式下点代表所有字符,包括换行符和行结束符。
多行匹配例子
例如下图未进行多行匹配是无法区分换行符\n的,因此导致下面输出第一个只能匹配到一个a,而加上多行匹配后第二个能匹配到2个a。
var reg1 = /^a/g,
reg2 = /^a/gm,
str = 'abc\nabc';
console.log(str.match(reg1));
console.log(str.match(reg2));
RegExp对象属性
reg.global
判断是否设置了'g'修饰符。
reg.ignoreCase
判断是否设置了'i'修饰符。
reg.lastIndex
用于规定下一次匹配的起始位置,默认是0(为n时,代表匹配的光标在str[n]和str[n-1]之间),搭配RegExp对象上的test和exec方法使用。
reg.multiline
判断是否设置了'm'修饰符。
reg.source
返回正则表达式的匹配模式(字符串模式的pattern)。
RegExp对象方法
reg.compile(str)
方法用于改变 RegExp。还可以通过第二个参数(可选参数)改变检索模式。
var reg=/hello/;
console.log(reg.exec('hellojs'));//['hello']
reg.compile('Hello');
console.log(reg.exec('hellojs'));//null
reg.compile('Hello','i');
console.log(reg.exec('hellojs'));//['hello']
reg.exec(str)
匹配到返回一个长度为1的数组包含匹配到的内容(如果reg中带有(),则该数组长度将不为1,数组[1]中存了第一个括号匹配的内容,依次类推),它有index属性表示匹配到的字符串在str中的索引,还有input属性为str字符串。
注意起始匹配的位置为reg.lastIndex默认为0,每次只会匹配到1个符合条件的内容,如果是/g全局匹配,则将reg.lastIndex=index+匹配到字符串的长度。
未匹配到返回null,且将reg.lastIndex=0。
exec使用例子
注意reg2由于每次匹配到空串,而空串的长度为0,会导致reg.lastIndex=index+匹配到字符串的长度=0,所以一直匹配的都是开头的空串,并不会匹配到a,这里建议使用match方法,match即使是空串或单词边界,reg.lastIndex也会默认加1。
var str1 = 'W3School1111111W3School';
var reg1 =/W3School/g
reg1.exec(str1)
//['W3School', index: 0, input: 'W3School1111111W3School', groups: undefined]
reg1.exec(str1)
//['W3School', index: 15, input: 'W3School1111111W3School', groups: undefined]
reg1.exec(str1)
//null
reg1.exec(str1)
//['W3School', index: 0, input: 'W3School1111111W3School', groups: undefined]
var reg2 = /(|a)/g
var str2 = '123a'
reg.exec(str)
//['', '', index: 0, input: '123a', groups: undefined]
reg.exec(str)
//['', '', index: 0, input: '123a', groups: undefined]
reg.test(str)
检测str字符串是否有符合正则表达式reg匹配的字符串,匹配光标开始的位置为reg.lastIndex,返回true或false。注意起始匹配的位置为reg.lastIndex默认为0,如果是/g全局匹配,每次匹配到后,则将reg.lastIndex=index+匹配到字符串的长度,当未匹配到时将reg.lastIndex=0。。
支持正则表达式的String对象的方法
注意/g全局查找每次找到后,从下一个没查找过的开始,而不是从下一位开始。
string.search(reg)
检索与正则表达式相匹配的值。返回字符串string中指定文本第一次出现的索引位置,没找到返回-1。搭配~-1=0,可以用于if判断 。
string.match(reg)
找到一个或多个正则表达式的匹配。返回一个数组,没找到返回null。
match例子
reg1匹配空串或1,虽然匹配到了空串但是reg.lastIndex依然会加1,最后结果匹配到5个空串。
reg2匹配开头的空串或1,第一次匹配到了开头的空串,第二次reg.lastIndex会加1,匹配从2开始,所以只能匹配到一个开头的空串。
reg3匹配开头的空串或2,第一次匹配到了开头的空串,第二次匹配从2开始,所以能匹配到开头的空串和2。
var reg1 = /(|1)/g
var str = '123a'
str.match(reg1)
//['', '', '', '', '']
var reg2 = /(^|1)/g
str.match(reg2)
//['']
var reg3 = /(^|2)/g
str.match(reg3)
//['', '2']
string.replace(str1,str2)
返回字符串string中首次出现的str1字符串内容替换成str2字符串后的新字符串。
str1可以传正则表达式,默认情况是对大小写敏感的,且只会替换1次,可通过正则表达式/i和/g修改。不传参数或传一个参数,默认都是返回原字符串。
$1、$2等使用
注意str2中可以用$1、$2等代表str1正则表达式情况的第一个括号、第二个括号等匹配到的内容(如果需要$本身,则需要写成$$)。
注意这里不能对$1进行字符串上的操作比如"$1".toUpperCase(),这样的传入,后面的函数会失效。
例如下面将名字顺序互换。
var str = "Doe, John";
str.replace(/(\w+), \s*(\w+)/, "$2 $1");
//'John Doe'
str2为function
str2也可以是个function返回字符串(和sort中函数相似),系统会默认给arguments[0]赋值为str1正则表达式匹配内容,arguments[1]赋值为str1正则表达式中的第一个括号匹配内容,依次类推。引用ES9的命名捕获用$<name>。
例如将以下换线开头的第一个字母转换为大写字母
'a_bd_ce'.replace(/_([a-z])/g,(v)=>{return v[1].toUpperCase()})
//'aBdCe'
string.split(reg)
把字符串分割为字符串数组。
以上函数具体使用方法链接
JavaScript中常用函数方法(字符串篇)_YF-SOD的博客-优快云博客_js常用字符串函数
RegExp静态属性
RegExp.$1
RegExp.$1是RegExp的一个属性,存储最近一次正则表达式括号中匹配的内容,支持$1~$9。
实例
var re = /(\w+)\s(\w+)/;
var str = 'John Smith';
str.replace(re, '$2, $1'); // "Smith, John"
RegExp.$1; // "John"
RegExp.$2; // "Smith"
年月日等日期格式化(简单应用)
Date.prototype.Format = function (fmt) {
let o = {
'y+': this.getFullYear(),//年
'M+': this.getMonth() + 1,//月份
'd+': this.getDate(),//日期
'h+': this.getHours(),//小时
'm+': this.getMinutes(),//分钟
's+': this.getSeconds(),//秒钟
'q+': Math.floor((this.getMonth() + 3) / 3),//季度
'S+': this.getMilliseconds()//毫秒
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
//将匹配到的格式替换为指定的时间,并按要求返回指定的位数
fmt = fmt.replace(RegExp.$1, ('00' + o[k]).substr(-RegExp.$1.length))
}
}
return fmt
}
let time = new Date()
time.Format('yyyy-MM-dd')//'2022-01-29'
RegExp.input
RegExp.input是RegExp的一个属性,存储最近一次使用正则表达式匹配的字符串。
实例
var re = /hi/g;
re.test('hi there!');
RegExp.input; // "hi there!"
re.test('foo'); // new test, non-matching
RegExp.$_; // "hi there!"
re.test('hi world!'); // new test, matching
RegExp.$_; // "hi world!"
方括号和括号
方括号是用于查找某个范围内的一个字符。括号用于区分一个整体。
[abc]
查找一个字符,可以是a、b、c。
[^abc]
查找一个字符,不能是a、b、c(^只有在方括号中表示非,其它的表示以什么开头)。
[0-9]
查找一个字符,可以是0、1、2、...、9。
[A-z]
查找一个字符,可以是A、B、...、Z、a、b、...、z。
(red|blue)
查找red或blue字符串,注意\1可以引用第一个括号中匹配到的字符串,\n要写在第n个括号之后不然会失效(系统默认为没写),要匹配特殊的符号,就在符号前加\,例如\\匹配的是\。
ES9命名捕获
通过?<name>将正则表达式中的中的括号匹配内容命名,存储在输出数组的groups属性上(括号的内容还是可以通过\n来反向引用的)。
命名捕获例子
下图输出打印的长度为2的数组,第一个为匹配内容,第二个为括号中捕获的内容,这个例子中是相同的,该数组会有个groups属性,没有命名捕获时,该属性为undefined,有命名捕获时,该属性指向一个对象,对象中的属性为命名值,value值为括号匹配内容,该groups指向{name:pyf}。注意反向引用可以通过\k<name>来引命名捕获的内容,同样\1还是会生效。
var reg1 = /(?<name>pyf)/,
str = 'handsomepyfhandsome';
console.log(str.match(reg1));
元字符
查找某个范围内的一个字符。
.
查找单个字符,可以匹配空格等,只除了换行符和行结束符([^/n/r])无法匹配,注意在方括号[]中.只代表.,不代表单个字符。
\w
查找数字、字母及下划线(/[0-9A-z_/)。
\W
查找\w字符([^0-9A-z_])。
\d
查找数字([0-9])。
\D
查找非数字([^0-9])。
\s
查找空白字符([\t\n\r\v\f])。
\S
查找非空白字符,包括空格符、制表符、回车符、换行符、垂直换行符、换页符。([^\t\n\r\v\f])。
\b
匹配单词边界(指空白符和单词之间称为单词边界,具体不占位)。
单词边界例子
如下图,reg2匹配到三个a字符,而reg1只匹配到1个a,因为reg1要求a是单词边界即空白符连接a(匹配到的是\n后面的a字符),如果要匹配中间的那个a字符,则可以用/a\b/匹配。
var reg1 = /\ba/g,
reg2 = /a/g
str = 'abca\nabc';
console.log(str.match(reg1));
console.log(str.match(reg2));
\B
匹配非单词边界。
\0
查找null字符。
\n
查找换行符,注意是字符串中写有\n,而不是字符串中敲了回车,下面同样。
\f
查找换页符。
\r
查找回车符。
\t
查找制表符。
\v
查找垂直制表符。
\xxx
查找以八进制数xxx转化为十进制数对应Unicode的字符。
\xdd
查找以十六进制数dd转化为10进制数对应Unicode的字符
\uxxxx(匹配汉字)
查找以十六进制数xxxx规定的Unicode字符。
匹配汉子用[\u4e00-\u9fa5]
注意这种形式是不匹配生僻字的,匹配生僻字见下面链接
用正则表达式匹配汉字,完整总结 - animalize - 博客园
量词
正则表达式匹配遵循贪婪匹配原则,匹配尽量多的符合要求的字符串,我们可以在量词后加?,来取消贪婪匹配,会匹配尽量少的符合要求的字符串。
n+
匹配任何包含1个或多个n的字符串
n*
匹配任何包含零个或多个n的字符串
n*例子
下图所示注意n*是包含了零个n即空串的,下面将输出长度为9位的数组["", "a", "", "a", "", "a", "", "", ""],系统的匹配规则是先光标放在b和单引号之间,发现不符合a要求,即返回空串,然后将光标后移,放到ba之间,发现匹配返回a,再接着后移放到ac之间,不匹配返回空串,接着有后移至a与空格之间,发现不匹配返回空串,以后依次类推。
var reg1 = /a*/g,
str = 'baca abc';
console.log(str.match(reg1));
n?
匹配任何包含零个或一个n的字符串(在量词后加?,可以来取消贪婪匹配,会匹配尽量少的符合要求的字符串)。
n{X}
X为正整数,匹配连续出现X次的n字符串(注意量词和元字符的结合时,不代表匹配出现多次一样内容,例如\\d{2}\仅代表2次的内容都是数字)。
n{X,Y}
X,Y为正整数,匹配连续出现X次~Y次的n字符串。
n$
匹配任何以n结尾的字符串(受/m影响每行都有开头和结尾)。
^n
匹配任何以n开头的字符串(受/m影响每行都有开头和结尾)。
?=n
叫正向预查或正向断言,匹配任何其后紧接指定字符串n的字符串,注意正向预查之后不能在连接其它匹配内容,且需要用括号括起来,不然问号会理解为包含0个或一个。
正向预查例子
如下图将匹配到第一个b后面的第一个a,reg1表示匹配一个a,但要求a后面还接有一个a。
var reg1 = /a(?=a)/g,
str = 'baab';
console.log(str.match(reg1));
?<=n
反向预查或反向断言,匹配任何前面紧跟字符串n的字符,和上例相反。注意需要用括号括起来,不然问号会理解为包含0个或一个。
反向预查例子
如下图将匹配到第一个b后面的第二个a,reg1表示匹配一个a,但要求a前面还有一个a。
var reg1 = /(?<=a)a/g,
str = 'baab';
console.log(str.match(reg1));
?!n
匹配任何其后不紧接指定字符串n的字符串(和正向预查相反),注意需要用括号括起来,不然问号会理解为包含0个或一个。
?<!n
匹配任何前面不紧接字符串n的字符(和反向预查相反),注意需要用括号括起来,不然问号会理解为包含0个或一个。
?:(非捕获分组)
用于取消捕获分组。()表示捕获分组,()会把每个分组里的匹配的值保存起来,使用'$n'(n是一个数字,表示第n个捕获组的内容)。
注意引用捕获分组时,$数字要带上字符串符号(引号)。
取消捕获分组例子
var reg1 = /(?:12)(34)(56)/,reg2 = /(12)(34)(56)/
'123456'.match(reg1)
//['123456', '34', '56', index: 0, input: '123456', groups: undefined]
'123456'.match(reg2)
//['123456', '12', '34', '56', index: 0, input: '123456', groups: undefined]
'123456'.replace(reg1,'$1')
//34
运算符优先级
正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。
相同优先级的从左到右进行运算,不同优先级的运算先高后低。下表从最高到最低说明了各种正则表达式运算符的优先级顺序:
| 运算符 | 描述 |
|---|---|
| \ | 转义符 |
| (), (?:), (?=), [] | 圆括号和方括号 |
| *, +, ?, {n}, {n,}, {n,m} | 限定符 |
| ^, $, \任何元字符、任何字符 | 定位点和序列(即:位置和顺序) |
| | | 替换,"或"操作 字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",请使用括号创建子表达式,从而产生"(m|f)ood"。 |
题目
金额格式
输入金额的要求:整数位最多九位,小数为最多为两位,可以无小数位 ,0.00~999999999.99。
^([1-9]\d{0,9}|0)(\.\d{1,2})?$
[1-9]\d以1~9开始的数字,{0,9}至少匹配0次,至多匹配9次;
|0或者整数部分匹配0;
(\.)匹配小数点;
\d{1,2}匹配一位或者两位小数;
?匹配小数部分0次或1次。
千位分割
要求每隔3位数添加逗号,1123141513.2314=>1,123,141,513.234。
let num = "1279798668734567.14213";
console.log(num.replace(/(\d)(?=(?:\d{3})+\.)/g,'$1,'))//带小数的
num = "1279798668734567";
console.log(num.replace(/(\d)(?=(?:\d{3})+)/g,'$1,'))//纯整数的
本文详细介绍了正则表达式的创建、修饰符、多行匹配、属性与方法,如`RegExp.compile()`、`exec()`、`test()`等,并展示了日期格式化、元字符、量词和命名捕获等高级用法。同时涵盖了金额验证、千位分隔以及常用正则表达式示例。
3238

被折叠的 条评论
为什么被折叠?



