介紹
正則表達(dá)式是用于匹配字符串中字符組合的模式吆视。在 JavaScript中菌羽,正則表達(dá)式也是對(duì)象卤恳。這些模式被用于
RegExp
的exec
和test
方法, 以及String
的match
、matchAll
剔猿、replace
绑蔫、search
和split
方法。
正則對(duì)象
要使用正則表達(dá)式,就必須在程序創(chuàng)建
其中作谚,有兩種創(chuàng)建方式
正則對(duì)象
- 1. 隱式創(chuàng)建
const reg = /\d/gi // 匹配模式/匹配標(biāo)志
// 動(dòng)態(tài)正則匹配
const regSubstring = '0123456789'.substring(4, 7)
const reg = eval(`/${regSubstring}/g`)
- 2. 直接實(shí)例化
/**
* @param {string | RegExp} RegExp 匹配模式
* @param {string} mode 匹配標(biāo)志
*/
const reg = new RegExp('abcd', 'gi')
// 動(dòng)態(tài)正則匹配
let name1 = "xxx";
const reg1 = new RegExp(name) // /xxx/
let name2 = "xxx\\d";
const reg2 = new RegExp(name) // /xxx\d/
- 3. 區(qū)別
const reg = /\d/gi
// 如果直接實(shí)例化,那么像"\d"這樣的字符庵芭,需要轉(zhuǎn)義"\\d"
const reg = new RegExp("\\d","gi")
匹配標(biāo)志
-
g
lobal: 全局搜索妹懒。保留最后一個(gè)匹配項(xiàng)的索引,允許迭代搜索双吆。 -
case
i
nsensitive: 忽略大小寫眨唬。 使整個(gè)表達(dá)式不區(qū)分大小寫。 -
m
ultiline: 多行好乐。 起點(diǎn)/終點(diǎn)錨點(diǎn)(^/$)
將與一行的起點(diǎn)/終點(diǎn)匹配匾竿。 -
s
ingle line (dotall): Dotall。Dot(.)
將匹配任何字符蔚万,包括換行符岭妖。 -
u
nicode: Unicode反璃。 啟用\x{FFFFF}
Unicode轉(zhuǎn)義昵慌。 -
stick
y
: sticky淮蜈。 該表達(dá)式只會(huì)從其lastIndex
位置進(jìn)行匹配斋攀,并忽略全局(g)
標(biāo)志(如果已設(shè)置)。
如果使用正則對(duì)象
在js中梧田,使用正則對(duì)象主要有兩種用法:
RegExp類
-
test:方法執(zhí)行一個(gè)檢索淳蔼,用來查看正則表達(dá)式與指定的字符串是否匹配。返回
true
或false
參數(shù):用來與正則表達(dá)式匹配的
字符串
返回值:如果正則表達(dá)式與指定的字符串匹配 裁眯,返回true
鹉梨;否則false
。
// 語法: regexObj.test(str)
const str = 'hello world!'
let result = /^hello/.test(str)
console.log(result) // true
注意?? : 當(dāng)設(shè)置全局標(biāo)志的正則使用
test()
如果正則表達(dá)式設(shè)置了全局標(biāo)志穿稳,
test()
的執(zhí)行會(huì)改變正則表達(dá)式 lastIndex屬性俯画。連續(xù)的執(zhí)行test()
方法,后續(xù)的執(zhí)行將會(huì)從 lastIndex 處開始匹配字符串司草,exec()
同樣改變正則本身的 lastIndex屬性值)
- lastIndex: 是正則表達(dá)式的一個(gè)可讀可寫的整型屬性,用來指定下一次匹配的起始索引泡仗。
const regex = /foo/g; console.log(regex.lastIndex) // 0 regex.test('foo') // true console.log(regex.lastIndex) // 3 regex.test('foo') // false
參數(shù):要匹配正則表達(dá)式的
字符串
返回值:如果匹配成功娩怎,exec()
方法返回一個(gè)數(shù)組(包含額外的屬性index
和input
搔课,參見下方表格),并更新正則表達(dá)式對(duì)象的 lastIndex 屬性截亦。完全匹配成功的文本將作為返回?cái)?shù)組的第一項(xiàng)爬泥,從第二項(xiàng)起柬讨,后續(xù)每項(xiàng)都對(duì)應(yīng)正則表達(dá)式內(nèi)捕獲括號(hào)里匹配成功的文本。
// 語法: regexObj.exec(str)
// 匹配 "quick brown" 后跟 "jumps"袍啡,忽略中間的字符
// 記住 "brown" 跟 "jumps"
// Ignore case 忽略大小寫
const reg = /quick\s(brown).+?(jumps)/ig
let result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog')
// 結(jié)果:
// [
// 0: "Quick Brown Fox Jumps",
// 1: "Brown",
// 2: "Jumps",
// groups: undefined,
// index: 4,
// input: "The Quick Brown Fox Jumps Over The Lazy Dog",
// length: 3
// ]
下表列出這個(gè)腳本的返回值:
對(duì)象 | 屬性/索引 | 描述 | 例子 |
---|---|---|---|
result |
[0] |
匹配的全部字符串 | Quick Brown Fox Jumps |
result |
[1],...[n] |
括號(hào)中的分組捕獲 | [1] = Brown???????[2] = Jumps |
result |
index |
匹配到的字符位于原始字符串的基于0的索引值 | 4 |
result |
input |
原始字符串 | The Quick Brown Fox Jumps Over The Lazy Dog |
reg |
lastIndex |
下一次匹配開始的位置 | 25 |
reg |
ignoreCase |
是否使用了 "i " 標(biāo)記使正則匹配忽略大小寫 |
true |
reg |
global |
是否使用了 "g " 標(biāo)記來進(jìn)行全局的匹配. |
true |
reg |
multiline |
是否使用了 "m " 標(biāo)記使正則工作在多行模式(也就是踩官,^ 和 $ 可以匹配字符串中每一行的開始和結(jié)束(行是由 \n 或 \r 分割的),而不只是整個(gè)輸入字符串的最開始和最末尾處境输。) |
false |
reg |
source |
正則匹配的字符串 | quick\s(brown).+?(jumps) |
String類
- search: 匹配符合匹配模式的字符串出現(xiàn)的位置蔗牡。
參數(shù):一個(gè)正則表達(dá)式對(duì)象。如果傳入一個(gè)
非正則表達(dá)式
對(duì)象regexp
嗅剖,則會(huì)使用new RegExp(regexp)
隱式地將其轉(zhuǎn)換
為正則表達(dá)式對(duì)象辩越。
返回值:如果匹配成功,則search()
返回正則表達(dá)式在字符串中首次匹配項(xiàng)的索引
;否則信粮,返回-1
黔攒。
// 語法: str.search(regexp)
let str = "hey JudE";
const reg = /[A-Z]/g;
const reg1 = /[.]/g;
console.log(str.search(reg)) // 4, 這是第一個(gè)大寫字母“J”的索引
console.log(str.search(reg1)) // -1 找不到 “.” 點(diǎn)標(biāo)點(diǎn)
- match: 方法檢索返回一個(gè)字符串匹配正則表達(dá)式的結(jié)果。
參數(shù):一個(gè)
正則表達(dá)式
對(duì)象
- 如果傳入一個(gè)非正則表達(dá)式對(duì)象强缘,則會(huì)隱式地使用
new RegExp(obj)
將其轉(zhuǎn)換為一個(gè)RegExp
督惰。如果你沒有給出任何參數(shù)并直接使用match() 方法 ,你將會(huì)得到一 個(gè)包含空字符串的Array
:[""]返回值:
- 如果
使用g
標(biāo)志欺旧,則將返回與完整正則表達(dá)式匹配的所有結(jié)果姑丑,但不會(huì)返回捕獲組。- 如果
未使用g
標(biāo)志辞友,則僅返回第一個(gè)完整匹配及其相關(guān)的捕獲組(Array)栅哀。 在這種情況下,返回的項(xiàng)目將具有如下所述的其他屬性称龙。- 如果正則表達(dá)式不包含
g
標(biāo)志留拾,str.match()
將返回與 RegExp.exec() 相同的結(jié)果。
// 語法: str.match(regexp)
let str = 'For more information, see Chapter 3.4.5.1';
const reg = /see (chapter \d+(\.\d)*)/i;
let found = str.match(reg);
console.log(found);
// [
// 0: 'see Chapter 3.4.5.1',
// 1: 'Chapter 3.4.5.1',
// 2: '.1',
// groups: undefined,
// index: 22,
// input: 'For more information, see Chapter 3.4.5.1'
// ]
// 'see Chapter 3.4.5.1' 是整個(gè)匹配鲫尊。
// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕獲痴柔。
// '.1' 是被'(\.\d)'捕獲的最后一個(gè)值。
// 'index' 屬性(22) 是整個(gè)匹配從零開始的索引疫向。
// 'input' 屬性是被解析的原始字符串咳蔚。
- replace: 使用指定的內(nèi)容替換匹配模式的字符串。
參數(shù):
- regexp (
pattern
):一個(gè)RegExp
對(duì)象或者其字面量搔驼。該正則所匹配的內(nèi)容會(huì)被第二個(gè)參數(shù)
的返回值替換掉
谈火。- substr (
pattern
):一個(gè)將被newSubStr
替換的字符串
。其被視為一整個(gè)字符串舌涨,而不是一個(gè)正則表達(dá)式糯耍。僅第一個(gè)匹配項(xiàng)會(huì)被替換。- newSubStr (
replacement
):用于替換掉第一個(gè)參數(shù)在原字符串中的匹配部分的字符串
。該字符串中可以內(nèi)插一些特殊的變量名温技。- function (
replacement
): 一個(gè)用來創(chuàng)建新子字符串的函數(shù)革为,該函數(shù)的返回值將替換掉第一個(gè)參數(shù)匹配到的結(jié)果。返回值:一個(gè)部分或全部匹配由替代模式所取代的新的字符串舵鳞。
// 語法: str.replace(regexp|substr, newSubStr|function)
// newSubStr: 必需震檩。一個(gè)字符串值。規(guī)定了替換文本或生成替換文本的函數(shù)系任。
// 下面是 特殊的變量名
// $1恳蹲、$2、...俩滥、$99: 與 regexp 中的第 1 到第 99 個(gè)子表達(dá)式相匹配的文本
// $$: 插入一個(gè) '$'
// $&: 與 regexp 相匹配的子串
// $`: 位于匹配子串左側(cè)的文本
// $': 位于匹配子串右側(cè)的文本
// $$: 直接量符號(hào)
let str = 'aaa-bbb-ccc'
str.replace('aaa', 'ddd') // ddd-bbb-ccc
str.replace(/ddd/, 'aaa') // aaa-bbb-ccc
str.replace(/(aaa)-/, '$1~') // aaa~bbb-ccc
str.replace(/\a/g, (item, index, str) => {
console.log(item, index, str) // a 0 aaa-bbb-ccc
return index // 最后返回結(jié)果:"012-bbb-ccc"
})
-
split: 方法使用指定的分隔符字符串將一個(gè)
String
對(duì)象分割成子字符串?dāng)?shù)組嘉蕾,以一個(gè)指定的分割字串來決定每個(gè)拆分的位置。
參數(shù):
separator:指定表示每個(gè)拆分應(yīng)發(fā)生的點(diǎn)的字符串霜旧。
separator
可以是一個(gè)字符串
或正則表達(dá)式
错忱。 如果純文本分隔符包含多個(gè)字符,則必須找到整個(gè)字符串來表示分割點(diǎn)挂据。如果在str
中省略或不出現(xiàn)分隔符以清,則返回的數(shù)組包含一個(gè)由整個(gè)字符串組成的元素。如果分隔符為空字符串崎逃,則將str原字符串中每個(gè)字符的數(shù)組形式返回掷倔。limit:一個(gè)整數(shù),限定返回的分割片段數(shù)量个绍。當(dāng)提供此參數(shù)時(shí)勒葱,
split
方法會(huì)在指定分隔符的每次出現(xiàn)時(shí)分割該字符串,但在限制條目已放入數(shù)組時(shí)停止巴柿。如果在達(dá)到指定限制之前達(dá)到字符串的末尾凛虽,它可能仍然包含少于限制的條目。新數(shù)組中不返回剩下的文本广恢。返回值:返回源字符串以分隔符出現(xiàn)位置分隔而成的一個(gè)
Array
// 例子1: separator 是字符串
let myString1 = 'Hello World. How are you doing?'
console.log(myString1.split(' '))
// ["Hello", "World.", "How", "are", "you", "doing?"]
console.log(myString1.split(' ', 3))
// ["Hello", "World.", "How"]
// 例子2: separator 是正則
let myString2 = 'Hello 1 word. Sentence number 2.'
let splits = myString2.split(/(\d)/)
console.log(myString2.split(/\d/))
// ["Hello ", " word. Sentence number ", "."]
console.log(myString2.split(/(\d)/))
// ["Hello ", "1", " word. Sentence number ", "2", "."] 如果正則中有子表達(dá)式凯旋,那么配置的 子表達(dá)式 也會(huì)被匹配進(jìn)去
子表達(dá)式()
let str = '12312312php2545fxx'
// 例如:/(\d)php/中的"(\d)"就是一個(gè)子表達(dá)式
捕獲
在正則匹配模式中,子表達(dá)式匹配到的內(nèi)容會(huì)被系統(tǒng)捕獲至系統(tǒng)的緩沖區(qū)中钉迷,我們稱之為捕獲
var str = '12312312php2545fxx'
// 例如:/(\d)php/ //2php 2就被捕獲至系統(tǒng) **1號(hào)** 的緩沖區(qū)中
反向引用
捕獲之后至非,可以在匹配模式中使用\n(n:數(shù)字)來引用系統(tǒng)的第n號(hào)緩沖區(qū)內(nèi)容
let str = '12312312php2545fxx'
// 例如:/(\d)php\1/ //匹配的就是2php2了,\1是引用了1號(hào)緩沖區(qū)中的2糠聪,因?yàn)閜hp前面的是2
- 例子
// + 匹配前面的子表達(dá)式一次或多次(大于等于1次)睡蟋。例如,“zo+”能匹配“zo”以及“zoo”枷颊,但不能匹配“z”。+等價(jià)于{1,}
// * 匹配前面的子表達(dá)式任意次。例如夭苗,zo*能匹配“z”信卡,也能匹配“zo”以及“zoo”。*等價(jià)于{0,}题造。
// \w 匹配包括下劃線的任何單詞字符傍菇。類似但不等價(jià)于“[A-Za-z0-9_]”,這里的"單詞"字符使用Unicode字符集
// \W 匹配任何非單詞字符界赔。等價(jià)于“[^A-Za-z0-9_]”
// . 匹配除“\n”和"\r"之外的任何單個(gè)字符丢习。要匹配包括“\n”和"\r"在內(nèi)的任何字符,請(qǐng)使用像“[\s\S]”的模式淮悼。
let str1 = 'qewqsjava111javadssphp222php9uiyu33owds'
const reg1 = /(\W+)\d\d\d\1/gi;
str.match(reg1)
// 結(jié)果java111java, php222php
const reg2 = /(\w+)\d\d\d\1/gi;
let result;
while (result=reg2.exec(str)) {
alert(result)
}
// result[0]:java111java 這是匹配到的內(nèi)容
// result[1]:java 這里是第一個(gè)子表達(dá)式的值
// result[0]:php222php
// result[1]:php
// 查找連續(xù)相同的四個(gè)數(shù)字咐低,如:1208
const reg = /\d\d\d\d/gi //或者var reg = /\d{3}/gi
// 查找連續(xù)相同的四個(gè)數(shù)字,如:1111
const reg = /\d\1\1\1/gi
// 查找數(shù)字袜腥,如:1221见擦,3443
const reg = /(\d)(\d)\2\1/gi //1111這樣的也會(huì)匹配到
// 查找字符,如:AABB,TTMM
const reg = /(\w)\1(\w)\2/gi
// 查找連續(xù)相同的四個(gè)數(shù)字或四個(gè)字符
const reg = /(\w)\1\1\1/gi
// 再一個(gè)字符串羹令,查找一對(duì)html標(biāo)記以及中間的內(nèi)容
let str2 = iqeos<div>標(biāo)簽</div>adasdda<p>100.00p</p>qewq
const reg = /<(\w+)>.*<\/\1>/gi
一般情況下鲤屡,后面的內(nèi)容要求與前面的一致,就會(huì)用的子表達(dá)式福侈、捕獲酒来、反向引用
-
exec方法和match方法的比較:
exec
方法是RegExp
類下的方法
match
是String
下的方法
match
方法直接返回一個(gè)數(shù)組
exec
方法需要循環(huán)反復(fù)調(diào)用
如果有子表達(dá)式,exec
方法將子表達(dá)式的捕獲結(jié)果放到數(shù)字對(duì)應(yīng)的元素中
正則語法
普通字符:a-z,0-9 等等
特殊字符(元字符):\d \s \w . * 等等
-
(1)限定符
限定符可以指定正則表達(dá)式的一個(gè)給定組件必須要出現(xiàn)多少次才能滿足匹配
* 匹配前面的組件零次或者多次
+ 匹配前面的組件一次或者多次
? 匹配前面的組件零次或者一次
{n} 匹配確定的 n 次
{n,} 至少匹配 n 次
{n,m} 最少匹配 n 次且最低匹配 m 次
-
* , + , ? 也可以用下面的方式表示
-
*
{0,} -
+
{1,} -
?
{0,1}
-
-
(2)字符匹配符
-
字符匹配符用于匹配某個(gè)或某些字符
帶有[]的叫字符簇,一個(gè)簇表示一個(gè)字符
[a-z]
:表示 a-z 任意一個(gè)字符
[A-Z]
:表示 A-Z 任意一個(gè)字符
[0-9]
:表示0-9任意一個(gè)字符
[0-9a-z]
:表示 0-9 a-z 任意一個(gè)字符
[0-9a-zA-Z]
:表示 0-9 a-z A-Z任意一個(gè)字符
[abcd]
:表示a或b或c或d 任意一個(gè)字符
[1234]
:表示1或2或3或4 任意一個(gè)字符
[^a-z]
:表示除了 a-z 以外的任意字符
[^0-9]
:表示除了0-9以外的任意字符
[^abcd]
:表示除了1或2或3或4 以外的任意字符
\d
:匹配一個(gè)數(shù)字字符[0-9]
\D
:匹配一個(gè)非數(shù)字字符[^0-9]
\w
:匹配包括下劃線的任意單詞字符[0-9a-zA-Z_]
\W
:匹配任何非單詞字符[^0-9a-zA-Z_]
\s
:匹配任何空白字符 (空格衡奥、制表符、換行符)
\S
:匹配任何非空白字符
.
:匹配除 “\n” 之外的任何單個(gè)字符
-
-
(3)定位符
定位符可以將一個(gè)正則表達(dá)式固定在一行的開始或者結(jié)束远荠。也可以創(chuàng)建只在單詞內(nèi)或只在單詞的開始或者結(jié)尾處出現(xiàn)的正則表達(dá)式
^
:匹配字符串的開始位置
$
:匹配字符串的結(jié)束位置
\b
:匹配單詞的開始位置或結(jié)束位置
\B
:匹配不是單詞開頭位置或結(jié)束位置
注意:在字符簇的^跟不表達(dá)式里^是不同意思的
- 例如
[^x]
:匹配除了x以外的任意字符
[^aeiou]
:匹配除了aeiou這幾個(gè)字母以外的任意字符const reg = /^a/ //表示匹配第一個(gè)位置a const reg1 = /\Ba\B/ //表示匹配前后都不是單詞邊界的a
- 例子:驗(yàn)證年齡
const reg = /^/d/d $/g
- 例如
(4)轉(zhuǎn)義符
\
:用于匹配某些特殊字符-
(5)選擇匹配符
|
:可以匹配多個(gè)規(guī)則- 例子:
const str = 'hello Java,hello JavaScript' const reg = /hello (JavaScript|Java)/g console.log(str.match(reg)) // ["hello Java", "hello JavaScript"]
(6)關(guān)于正則表達(dá)式的幾種特殊用法
名稱 | 正則 | 描述 |
---|---|---|
(?:x) 非捕獲組(Non-capturing group ) |
/(?:\d)/.exec('2019') |
使用了() 捕獲矮固,不會(huì)出現(xiàn)在捕獲中 |
(?=) 正向前瞻 (Negative lookahead ) 也叫先行斷言
|
x(?=y) |
匹配x 僅僅當(dāng)x 后面跟著y 這種叫做 先行斷言
|
x(?!y) ****(Positive lookahead ) |
(?=)
正向前瞻:
let str = 'xxx好人,xxx好好人'
const reg = /xxx(?=好人)/gi
console.log(str.match(reg)) // ["xxx"](xxx好人的xxx)
- 例如:
\d{3,5}
//匹配最少3個(gè)最多5個(gè)的數(shù)子
const str = 'jau123123122wjqei78781h123ui131213aa'
const reg = /\d{3,5}/gi
console.log(str.match(reg))
// 結(jié)果:["12312", "3122", "78781", "123", "13121"]
上面這個(gè)例子中,既匹配三個(gè)譬淳,也可以匹配五個(gè)档址,那么,正則表達(dá)式中會(huì)自動(dòng)匹配最多的那一種邻梆,這在正則中叫貪婪匹配原則
在表達(dá)式的后面使用" ? "守伸,表示非貪婪匹配原則,但是不會(huì)去匹配4個(gè)數(shù)字或者5個(gè)數(shù)字了
- 例如
const str = '123456q1234e12345'
const reg = /\d{3,5}?/gi
console.log(str.match(reg))
//結(jié)果: ["123", "456", "123", "123"]
- 例子:替換重復(fù)的字
let str = '我..是是.是.一一個(gè)個(gè)..好好.好人.人人'
let reg = /\.+/g
str = str.replace(reg,'') // "我是是是一一個(gè)個(gè)好好好人人人"
reg = /(.)\1+/g
str = str.replace(reg,'$1') // "我是一個(gè)好人"
// $1是1號(hào)緩沖區(qū)內(nèi)容替換重復(fù)的內(nèi)容
- 例子:驗(yàn)證ip是否有效
// 規(guī)則
// 例子 1.1.1.1
// 0-255
// 第一個(gè)段不能是0
// 不能以0開頭 如:011
const ip = '192.168.0.32'
const reg = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/g
if (reg.test(ip)) {
console.log('合法')
} else{
console.log('不合法')
}
- 例子:驗(yàn)證郵箱是否有效
const email = '347904341@cctv.admin.pl'
const reg = /^[\w\.]+@(\w+\.)+[a-z]{2,5}$/gi
if (reg.test(email)) {
console.log('合法')
} else{
console.log('不合法')
}
- 例子: 密碼強(qiáng)度校驗(yàn)浦妄,密碼6-20位尼摹,包括至少1個(gè)大寫字母见芹,1個(gè)小寫字母,1個(gè)數(shù)字蠢涝,1個(gè)特殊字符
const reg = /^(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[.!@#$%^&? ])\S{6,20}$/
reg.test('123Aa!') // true
reg.test('45678901234567890Aa!') // true
reg.test('456789012345678901Aa!') // false