JavaScript必會技能——正則表達式

正則表達式是什麼

RegExp 對象表示正則表達式,它是對字符串執行模式匹配的強大工具。javascript

爲何使用正則表達式

  • 測試字符串內的模式。例如,能夠測試輸入字符串,以查看字符串內是否出現電話號碼模式或信用卡號碼模式。這稱爲數據驗證。css

  • 替換文本。可使用正則表達式來識別文檔中的特定文本,徹底刪除該文本或者用其餘文本替換它。html

  • 基於模式匹配從字符串中提取子字符串。能夠查找文檔內或輸入域內特定的文本。java

語法

正則表達式有兩種方法定義:node

1.直接量語法git

/pattern/attributes

2.建立 RegExp 對象的語法:github

new RegExp(pattern, attributes);

參數:參數pattern是一個字符串,指定了正則表達式的模式;參數attributes是一個可選的參數,包含屬性g,i,m,分別使用與全局匹配,不區分大小寫匹配,多行匹配;
返回值:一個新的RegExp對象,具備指定的模式和標誌;正則表達式

修飾符

修飾符 說明
g 執行全局匹配(查找全部匹配而非在找到第一個匹配後中止)。
i 執行不分大小寫匹配。
m 執行多行匹配。

括號

方括號包含一系列字符,能夠匹配它所包含的任意字符;同時能夠經過^符號來定義否認字符類數組

表達式 說明
[abc] 查找在方括號中的任意一個字符
[^abc] 查找不在方括號中的任意一個字符
[0-9] 查找0-9中的任意一個數字
[a-z] 查找任何從小寫 a 到小寫 z 的字符
[A-Z] 查找任何從大寫 a 到大寫 z 的字符
(red | blue | green) 查找小括號中的任意一項,小括號中的|是或者的意思

元字符

元字符 說明
. 查找任意的單個字符,除換行符和其餘Unicode行終止符以外
\w 查找字母數字和下劃線 ,等價於[a-zA-Z0-9_]
\W 查找除字母數字下劃線以外的字符,等價於[^a-zA-Z0-9_]
\d 查找數字字符,等價於[0-9]
\D 查找非數字字符,等價於[^0-9]
\s 匹配任何空白字符,包括空格,製表符,換行符等等。等價於[\f\n\r\t\v]
\S 匹配任何非空白字符,等價於[^\f\n\r\t\v]
\b 查找一個單詞邊界,也就是指單詞和空格間的位置,好比er\b能夠匹配"never"中的"er",可是不能匹配"verb"中的"er"
\B 查找非單詞邊界,er\B能匹配"ver"中的"er",但不能匹配"never"中的"er"
\0 查找空字符("")
\n 查找換行符
\r 查找回車符
\f 查找換頁符
\t 查找製表符
\v 查找垂直製表符

量詞

量詞 說明
n+ 匹配任何至少包含一個n的字符串,等價於n{1,}
n* 匹配零個或者多個n的字符串,等價於n{0,}
n? 匹配零個或者1個n的字符串,等價於n{0,1}
n{x} 匹配包含x個n的序列字符串
n{x,y} 匹配至少x個,最多y個n的字符串
n{x,} 匹配至少x個n的字符串
n$ 匹配以n結尾的字符串
^n 匹配以n開頭的字符串

正則表達式的特殊字符中須要轉義字符

正則表達式中的特殊字符都有它們的特殊含義,因此當咱們要匹配這些特殊字符自己時,須要對字符進行轉義,轉義只須要在字符前面加上\,這些特殊字符包括$ ^ * + . [ ? { | ( ) \函數

支持正則表達式的方法

RegExp 對象方法

1.test方法:該方法用於檢測一個字符串是否匹配某個模式。

語法RegExpObject.test(str)
參數:str是須要檢測的字符串
返回值:若是字符串str中含有與RegExpObject匹配的文本的話,返回true,不然返回false

示例代碼以下:

var str = "longen and yunxi";
console.log(/longen/.test(str)); // true
console.log(/longlong/.test(str)); //false

2.exec方法:該方法用於檢索字符串中的正則表達式的匹配。

語法RegExpObject.exec(str)
參數:str是須要檢測的字符串
返回值:返回一個數組,存放匹配的結果,若是未找到匹配,則返回值爲null

示例代碼以下:

var str = "javascript html css";
console.log(/html/.exec(str)); // ["html", index: 11, input: "javascript html css"]
返回的數組的第一個元素是與正則表達式相匹配的文本,該方法還返回2個屬性,index屬性聲明的是匹配文本的第一個字符的位置;input屬性則存放的是被檢索的字符串string。

// 假如沒有找到的話,則返回null
console.log(/node/.exec(str)); // null

支持正則表達式的 String 對象的方法

1.search方法:該方法用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的字符串。

語法stringObject.search(regexp)
參數:regexp能夠是在stringObject中檢索的字符串,也能夠是須要檢索的RegExp對象
返回值:stringObject中第一個與regexp對象相匹配的子串的起始位置。若是沒有找到任何匹配的子串,則返回-1;

示例代碼以下:

var str = "hello world,hello world";
// 返回匹配到的第一個位置
console.log(str.search(/hello/)); // 0
// search方法不執行全局匹配,它將忽略標誌g,同時它也沒有regexp對象的lastIndex的屬性,且老是從字符串開始位置進行查找,老是返回的是stringObject匹配的第一個位置。
console.log(str.search(/hello/g)); //0
console.log(str.search(/world/)); // 6

// 也能夠是檢索字符串中的字符
console.log(str.search("wo")); // 6

// 若是沒有檢索到的話,則返回-1
console.log(str.search(/longen/)); // -1

// 咱們檢索的時候 能夠忽略大小寫來檢索
var str2 = "Hello";
console.log(str2.search(/hello/i)); // 0

2.match方法:該方法用於在字符串內檢索指定的值,或找到一個或者多個正則表達式的匹配。該方法相似於indexOf()或者lastIndexOf(); 可是它返回的是指定的值,而不是字符串的位置。

語法stringObject.match(regexp)
參數:regexp能夠是在stringObject中檢索的字符串,也能夠是須要檢索的RegExp對象
返回值:存放匹配成功的數組;若是沒有找到任何的一個匹配,那麼它將返回的是null。

示例代碼以下:

var str = "hello world";
// 返回的數組內有三個元素,第一個元素的存放的是匹配的文本,還有二個對象屬性;index屬性代表的是匹配文本的起始字符在stringObject中的位置;input屬性聲明的是對stringObject對象的引用;
console.log(str.match("hello")); // ["hello", index: 0, input: "hello world"]
console.log(str.match("Hello")); // null
console.log(str.match(/hello/)); // ["hello", index: 0, input: "hello world"]

// 全局匹配也返回一個數組,但有些不同;它的數組元素中存放的是 stringObject 中全部的匹配子串,並且也沒有 index 屬性或 input 屬性。
var str2="1 plus 2 equal 3"
console.log(str2.match(/\d+/g)); //["1", "2", "3"]

3.replace方法:該方法用於在字符串中使用一些字符替換另外一些字符,或者替換一個與正則表達式匹配的子字符串。

語法stringObject.replace(regexp/substr,replacement);
參數:regexp/substr能夠是字符串或者是須要替換模式的RegExp對象;replacement能夠是替換的文本或者是生成替換文本的函數。
返回值:返回替換後的新字符串。

字符串 stringObject 的 replace() 方法執行的是查找並替換的操做。它將在 stringObject 中查找與regexp 相匹配的子字符串,而後用 replacement 來替換這些子串。若是 regexp 具備全局標誌 g,那麼replace() 方法將替換全部匹配的子串。不然,它只替換第一個匹配子串。

replacement能夠是字符串,也能夠是函數。若是它是字符串,那麼每一個匹配都將由字符串替換。可是 replacement 中的 $字符具備特定的含義。以下表所示,它說明從模式匹配獲得的字符串將用於替換。

字符 含義
$1$2、...、$99 與 regexp 中的第 1 到第 99 個子表達式相匹配的文本。
$& 與 regexp 相匹配的子串。
$` 位於匹配子串左側的文本。
$' 位於匹配子串右側的文本。
$$ 表示美圓符號$。

示例代碼以下:

var str = "hello world";
// 使用字符串替換字符串
var s1 = str.replace("hello","a");
console.log(s1);// a world

// 使用正則替換字符串
var s2 = str.replace(/hello/,"b");
console.log(s2); // b world

// 使用正則全局替換字符串
var s3 = str.replace(/l/g,'');
console.log(s3); // heo word

// $1,$2 表明的是第一個和第二個子表達式相匹配的文本
// 子表達式須要使用小括號括起來,表明的含義是分組
var name = "longen    ,yunxi";
var s4 = name.replace(/(\w+)\s*,\s*(\w+)/,"$2 $1");
console.log(s4); // "yunxi,longen"

console.log('hello world'.replace(/w/g, '$&')) //hello world
console.log('hello world'.replace(/w/g, '$$')) //hello $orld
console.log('hello world'.replace(/w/g, '$`')) //hello hello orld
console.log('hello world'.replace(/w/g, "$'")) //hello orldorld

// replace 第二個參數也能夠是一個function 函數
// 單詞首字母大寫
var name = 'aaa bbb ccc';
var uw=name.replace(/\b\w+\b/g, function(word){
    return word.substring(0,1).toUpperCase()+word.substring(1);}
);
console.log(uw) //Aaa Bbb Ccc


var name2 = "123cbc45678rtyu909876pjkl54321";
name2.replace(/\d+/g,function(v){
    console.log(v); 
    /*
     * 第一次打印123
     * 第二次打印45678
     * 第三次打印909876
     * 第四次打印54321
     */
});
/*
 * 以下函數,回調函數參數一共有四個
 * 第一個參數的含義是 匹配的字符串
 * 第二個參數的含義是 正則表達式分組內容,沒有分組的話,就沒有該參數,
 * 若是沒有該參數的話那麼第四個參數就是undefined
 * 第三個參數的含義是 匹配項在字符串中的索引index
 * 第四個參數的含義是 原字符串
 */
 name2.replace(/(\d+)/g,function(a,b,c,d){
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);
    /*
     * 如上會執行四次,值分別以下(正則使用小括號,表明分組):
     * 第一次: 123,123,0,123cbc45678rtyu909876pjkl54321
     * 第二次: 45678,45678,6,123cbc45678rtyu909876pjkl54321
     * 第三次: 909876,909876,15,123cbc45678rtyu909876pjkl54321
     * 第四次: 54321,54321,25,123cbc45678rtyu909876pjkl54321
     */
 });

4.split方法:該方法把一個字符串分割成字符串數組。

語法stringObject.split(separator,howmany)
參數
1.separator[必填項],字符串或正則表達式,該參數指定的地方分割stringObject;
2.howmany[可選] 該參數指定返回的數組的最大長度,若是設置了該參數,返回的子字符串不會多於這個參數指定的數組。若是沒有設置該參數的話,整個字符串都會被分割,不考慮他的長度。
返回值:一個字符串數組。該數組經過在separator指定的邊界處將字符串stringObject分割成子字符串。

示例代碼以下:

var str="How are you doing today?"
console.log(str.split(" ")) //["How", "are", "you", "doing", "today?"]
console.log(str.split("")) //["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y", "?"]
console.log(str.split(" ",3)) //["How", "are", "you"]

// 也可使用正則表達式
console.log(str.split(/\s+/)) //["How", "are", "you", "doing", "today?"]

貪婪模式與非貪婪模式

Javascript中的正則表達式貪婪模式與非貪婪模式的區別是:被量詞修飾的子表達式的匹配行爲;貪婪模式在整個表達式匹配成功的狀況下儘量多的匹配;非貪婪模式在整個表達式匹配成功的前提下,儘量少的匹配。

一些常見的修飾貪婪模式的量詞以下:
{x,y}{x,}?*+

非貪婪模式就是在如上貪婪模式後加上一個問號(?),就能夠變成非貪婪模式的量詞;以下:
{x,y}?{x,}???*?,和+?

示例代碼以下:

//貪婪模式,儘量多的匹配
console.log('0123456789'.replace(/\d{3,6}/,"*")) //*6789

//非貪婪模式,儘量少的匹配
console.log('0123456789'.replace(/\d{3,6}?/,"*")) //*3456789

分組與反向引用

分組,又稱爲子表達式。把正則表達式拆分紅小表達式。

直接上代碼:

//不分組,量詞僅做用到最後一個字符(c)
console.log(/abc{2}/.test('abcabc')); // false
console.log(/abc{2}/.test('abcc')); //true

//分組,量詞做用於整個括號裏的子表達式
console.log(/(abc){2}/.test('abcabc')); // true
console.log(/(abc){2}/.test('abcc')); //false

分組常常和反向引用一塊兒使用,反向引用在前面的replace方法就有了,只不過沒有說他的概念,這裏說一下:當一個正則表達式被分組後,每一個分組自動被賦予一個組號,一左到右分別是 $1 $2…
再舉個例子:

//格式化日期
var reg = /^(\d{4})[/-](\d{2})[/-](\d{2})$/
console.log('2016/11/18'.replace(reg, '$1年$2月$3日')) //2016年11月18日
console.log('2016-11-18'.replace(reg, '$1年$2月$3日')) //2016年11月18日
console.log('2016-11-18'.replace(reg, '$1$2$3')) //20161118

非捕獲性分組

不是全部分組都能建立反向引用,有一種分組叫作非捕獲性分組,非捕獲性分組以(?:pattern)表示,在一些只須要分組匹配可是並不須要獲得各個分組匹配的結果時,使用非捕獲性分組能夠提升匹配速度;非捕獲分組的含義咱們能夠理解爲以下:子表達式能夠做爲被總體修飾可是子表達式匹配的結果不會被存儲;以下:

var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var date = '2012-12-21'
reg.test(date)
RegExp.$1  // 12
RegExp.$2  // 21

這裏,(?:d{4})分組不會捕獲任何字符串,因此$1(d{2})捕獲的字符串。

零寬斷言

初學者第一次看到這個名詞可能有點懵逼(我第一次也不懂),這裏說明一下。

零寬斷言就是下結論,例如ab,正則:a(?=b),匹配a而且向右看是b,獲得的結果是a,斷言不會在匹配的內容當中,若是是a(?=c),則匹配不到任何內容,由於匹配a之後向右看並非c。另外,零寬斷言分兩種:前瞻(Lookahead)和後顧(Lookbehind);但JavaScript只支持前瞻

前瞻表達式的語法以下:

表達式 說明
m(?=n) 匹配後面緊接n的字符串m
m(?!n) 匹配後面沒有緊接n的字符串m

再兩個例子:

// 獲取字符串中以ing結尾的單詞的前半部分
var str = 'I love dancing but he likes singing';
var pattern = /\b\w+(?=ing\b)/g;
var ans = str.match(pattern);
console.log(ans); // ["danc", "sing"]


// 獲取第五位不是i的單詞的前四位
var s = 'I love dancing but he likes singing';
var pattern = /\b\w{4}(?!i)/g;
var ans = s.match(pattern);
console.log(ans); // ["love", "like"]

最後

正則表達式基礎知識差很少這些夠用了,後面就是多謝多運用。共勉!

推薦

最後推薦兩個比較好的工具,能幫助咱們寫出更好更準確的正則表達式。
正則表達式圖形化工具
正則表達式檢測工具

博客地址

參考

JavaScript RegExp 對象
深刻淺出的javascript的正則表達式學習教程

相關文章
相關標籤/搜索