DailyENJS 致力于翻譯優(yōu)秀的前端英文技術(shù)文章,為技術(shù)同學(xué)帶來(lái)更好的技術(shù)視野。
當(dāng)你第一次遇到正則表達(dá)式時(shí),它們看起來(lái)像是隨意的亂碼。雖然它們可能看起來(lái)不容易理解,但它們也非常有用。
事實(shí)上正確理解正則表達(dá)式將使你成為一個(gè)更加高效的程序員。為了完全理解正則表達(dá)式,您首先需要學(xué)習(xí)基礎(chǔ)知識(shí)。
什么是正則表達(dá)式
正則表達(dá)式是一種描述字符串?dāng)?shù)據(jù)中的模式的方法。它們構(gòu)成了自己的一種小語(yǔ)言,它是許多編程語(yǔ)言的一部分,如Javascript,Perl,Python,Php和Java。
正則表達(dá)式能夠幫助你去校驗(yàn)字符串,如電子郵件地址或密碼。
創(chuàng)建一個(gè)正則表達(dá)式
在Javascript中有兩種方式可以創(chuàng)建正則表達(dá)式。可以使用RegExp構(gòu)造函數(shù)創(chuàng)建,也可以使用正斜杠(/)來(lái)創(chuàng)建。
使用 RegExp 構(gòu)造函數(shù)
語(yǔ)法: new RegExp(pattern[, flags])
例子:
var regexConst = new RegExp('abc')
使用正則表達(dá)式字面量
語(yǔ)法: /pattern/flags
例子:
var regexLiteral = /abc/;
這里的 flags 是可選的,文章的后面將會(huì)解釋這些。
可能還有一些情況需要?jiǎng)討B(tài)創(chuàng)建正則表達(dá)式,在這種情況下,正則表達(dá)式字面量不起作用,因此您必須使用正則表達(dá)式構(gòu)造函數(shù)。
無(wú)論您選擇哪種方法,結(jié)果都是正則表達(dá)式對(duì)象,都有相同的方法和屬性。
由于正斜杠用于創(chuàng)建正則表達(dá)式,因此如果要將 / 用作正則表達(dá)式的一部分,則必須使用反斜杠(\)轉(zhuǎn)義正斜杠(/)。
正則表達(dá)式的方法
測(cè)試正則表達(dá)式主要有兩種方法。
RegExp.prototype.test()
這個(gè)方法用于測(cè)試是否已找到匹配項(xiàng)。它接受一個(gè)字符串作為參數(shù),并返回true或false:
例子:
var regex = /hello/;
var str = 'hello world';
var result = regex.test(str);
console.log(result);
// returns true
RegExp.prototype.exec()
這個(gè)方法返回包含所有匹配組的數(shù)組。它接受一個(gè)字符串作為參數(shù)。
例子:
var regex = /hello/;
var str = 'hello world';
var result = regex.exec(str);
console.log(result);
// returns [ 'hello', index: 0, input: 'hello world', groups: undefined ]
// 'hello' -> is the matched pattern.
// index: -> Is where the regular expression starts.
// input: -> Is the actual string passed.
我們將在下面使用test()方法。
簡(jiǎn)單的正則表達(dá)式匹配
它是最基本的模式,它簡(jiǎn)單地將文字文本與測(cè)試字符串相匹配。例如:
var regex = /hello/;
console.log(regex.test('hello world'));
// true
特殊字符
到目前為止,我們已經(jīng)創(chuàng)建了簡(jiǎn)單的正則表達(dá)式。現(xiàn)在,讓我們?cè)谔幚砀鼜?fù)雜的情況時(shí)充分利用正則表達(dá)式的全部功能。
例如,不是匹配特定的電子郵件地址,而是說(shuō)我們想要匹配許多電子郵件地址。這就是特殊字符發(fā)揮作用的地方。為了完全理解正則表達(dá)式,您必須記住特殊的符號(hào)和字符。
falgs
正則表達(dá)式有五個(gè)可選的flag或修飾符。讓我們討論兩個(gè)最重要的flag:
g:全局匹配;找到所有匹配,而不是在第一個(gè)匹配后停止
i:忽略大小寫(xiě)
您還可以在單??個(gè)正則表達(dá)式中組合修飾符。并且他們的順序?qū)Y(jié)果沒(méi)有任何影響。
接下來(lái)看看一些例子:
使用正則表達(dá)式字面量:
var regexGlobal = /abc/g;
console.log(regexGlobal.test('abc abc'));
// it will match all the occurence of 'abc', so it won't return
// after first match.
var regexInsensitive = /abc/i;
console.log(regexInsensitive.test('Abc'));
// returns true, because the case of string characters don't matter
// in case-insensitive search.
使用 RegExp 構(gòu)造函數(shù):
var regexGlobal = new RegExp('abc','g')
console.log(regexGlobal.test('abc abc'));
// it will match all the occurence of 'abc', so it won't return // after first match.
var regexInsensitive = new RegExp('abc','i')
console.log(regexInsensitive.test('Abc'));
// returns true, because the case of string characters don't matter // in case-insensitive search.
Character groups:
字符集[xyz]-字符集是一種在一個(gè)位置匹配不同字符的方法,它匹配括號(hào)內(nèi)的字符中字符串中的任何單個(gè)字符。例如:
var regex = /[bt]ear/;
console.log(regex.test('tear'));
// returns true
console.log(regex.test('bear'));
// return true
console.log(regex.test('fear'));
// return false
注: 除了插入符號(hào)(^)(在字符集中具有完全不同的含義)之外的所有特殊字符在字符集內(nèi)(中括號(hào)內(nèi))都會(huì)失去其特殊含義。
否定字符集(Negated character set [^xyz])—— 它匹配括號(hào)中未包含的任何內(nèi)容。例如:
var regex = /[^bt]ear/;
console.log(regex.test('tear'));
// returns false
console.log(regex.test('bear'));
// return false
console.log(regex.test('fear'));
// return true
范圍[a-z](Ranges[a-z]): 假設(shè)我們想要在一個(gè)位置匹配字母表中的所有字母,我們可以在括號(hào)內(nèi)寫(xiě)出所有字母,但有一種更簡(jiǎn)單的方法,那就是范圍。例如:[a-h]將匹配a到h的所有字母。范圍也可以是[0-9]之類(lèi)的數(shù)字或[A-Z]之類(lèi)的大寫(xiě)字母。
var regex = /[a-z]ear/;
console.log(regex.test('fear'));
// returns true
console.log(regex.test('tear'));
// returns true
元字符(Meta-characters) - 元字符是具有特殊含義的字符。有許多元字符,但我將在這里介紹最重要的元字符。
\d:匹配任何數(shù)字字符(與[0-9]相同)
\w: 匹配任何單詞字符。單詞字符是任何字母,數(shù)字和下劃線(xiàn)。(與[a-zA-Z0-9_]相同)即字母數(shù)字字符
\s: 匹配空白字符(空格,制表符等)
\t: 僅匹配制表符
\b: 在單詞的開(kāi)頭或結(jié)尾找到匹配項(xiàng)。也稱(chēng)為單詞邊界
.: 匹配除換行符之外的任何字符
\D: 匹配任何非數(shù)字字符(與[^ 0-9]相同)
\W: 匹配任何非單詞字符(與[^ a-zA-Z0-9_]相同)
\S: 匹配非空白字符
量詞: 量詞是在正則表達(dá)式中具有特殊含義的符號(hào)
- +: 匹配前面的表達(dá)式1次或多次
var regex = /\d+/;
console.log(regex.test('8'));
// true
console.log(regex.test('88899'));
// true
console.log(regex.test('8888845'));
- *: 匹配前面的表達(dá)式0次或更多次
var regex = /go*d/;
console.log(regex.test('gd'));
// true
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// true
- ?: 匹配前面的表達(dá)式0或1次,即前面的模式是可選的
var regex = /goo?d/;
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// false
- ^: 匹配字符串的開(kāi)頭。即插入符號(hào)(^)匹配字符串的開(kāi)頭。
var regex = /^g/;
console.log(regex.test('good'));
// true
console.log(regex.test('bad'));
// false
console.log(regex.test('tag'));
// false
-
)符號(hào)與字符串的結(jié)尾匹配。
var regex = /.com$/;
console.log(regex.test('test@testmail.com'));
// true
console.log(regex.test('test@testmail'));
// false
- {N}: 完全匹配前面表達(dá)式N次
var regex = /go{2}d/;
console.log(regex.test('good'));
// true
console.log(regex.test('god'));
// false
- {N,}: 匹配前面正則表達(dá)式至少N次
var regex = /go{2,}d/;
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// true
console.log(regex.test('gooood'));
// true
- {N,M}: 匹配前面正則表達(dá)式至少N次且最多M次(其中M> N)
var regex = /go{1,2}d/;
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// false
Alternation X|Y: 匹配X或Y,例如:
var regex = /(green|red) apple/;
console.log(regex.test('green apple'));
// true
console.log(regex.test('red apple'));
// true
console.log(regex.test('blue apple'));
// false
注意 - 如果要將任何特殊字符用作表達(dá)式的一部分,例如,您希望匹配文字+或。,則必須使用反斜杠(\)對(duì)其進(jìn)行轉(zhuǎn)義。
例如:
var regex = /a+b/; // This won't work
var regex = /a\+b/; // This will work
console.log(regex.test('a+b')); // true
高級(jí)
(x): 匹配x并記住這個(gè)匹配。這些被稱(chēng)為捕獲組。這也用于在正則表達(dá)式中創(chuàng)建子表達(dá)式。例如 :
var regex = /(foo)bar\1/;
console.log(regex.test('foobarfoo'));
// true
console.log(regex.test('foobar'));
// false
\1
記住并使用括號(hào)內(nèi)第一個(gè)子表達(dá)式匹配。
(?:x): 匹配x并且不記得匹配。這些被稱(chēng)為非捕獲組。這里 \1
不起作用,它將匹配文字 \1
var regex = /(?:foo)bar\1/;
console.log(regex.test('foobarfoo'));
// false
console.log(regex.test('foobar'));
// false
console.log(regex.test('foobar\1'));
// true
x(?=y): 僅當(dāng)x后跟y時(shí)才匹配x。也被稱(chēng)為正向先行斷言。例如:
var regex = /Red(?=Apple)/;
console.log(regex.test('RedApple'));
// true
在上面的示例中,僅當(dāng)Redis后跟Apple時(shí)才會(huì)進(jìn)行匹配。
正則表達(dá)式練習(xí)
讓我們練習(xí)一些我們上面學(xué)到的概念。
- 匹配任何10個(gè)數(shù)字:
var regex = /^\d{10}$/;
console.log(regex.test('9995484545'));
// true
讓我們看一看發(fā)生了什么。
如果我們想強(qiáng)制匹配整個(gè)字符串,我們可以添加量詞^和
匹配結(jié)尾。因此,如果字符串包含超過(guò)10位數(shù),則不匹配
\d
匹配數(shù)字字符串{10}
匹配前一個(gè)表達(dá)式,在這種情況下\d
恰好10次。因此,如果測(cè)試字符串包含少于或大于10位數(shù),則結(jié)果將為false。
- 匹配日期格式DD-MM-YYYY或DD-MM-YY
var regex = /^(\d{1,2}-){2}\d{2}(\d{2})?$/;
console.log(regex.test('01-01-1990'));
// true
console.log(regex.test('01-01-90'));
// true
console.log(regex.test('01-01-190'));
// false
讓我們看一看發(fā)生了什么。
- 同樣,我們將整個(gè)正則表達(dá)式包裝在^和$中,以便匹配整個(gè)字符串。
-
(
開(kāi)始第一個(gè)子表達(dá)式 -
\d{1,2}
匹配智商一個(gè)數(shù)字最多兩個(gè)數(shù)字 -
-
匹配連字符 -
)
第一個(gè)子表達(dá)式的結(jié)尾 -
{2}
精確匹配第一個(gè)子表達(dá)式2次 -
\d{2}
精確匹配兩個(gè)數(shù)字字符 -
(\d{2})?
精確匹配兩個(gè)數(shù)字并且是可選的
結(jié)論
正則表達(dá)式有時(shí)可能相當(dāng)復(fù)雜,但正確理解上述概念將有助于您輕松理解更復(fù)雜的正則表達(dá)式模式。
您可以在此處 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions 了解有關(guān)正則表達(dá)式的更多信息并可以在此處 https://www.hackerrank.com/domains/regex 練習(xí)。
最后照舊是一個(gè)廣告貼,最近新開(kāi)了一個(gè)分享技術(shù)的公眾號(hào),歡迎大家關(guān)注??(目前關(guān)注人數(shù)可憐??)