【正則表達式系列】基本用法

前言

快速入門一文中,示例都是經過test()方法演示,本文會繼續介紹正則的其它用法(以JS語言爲例)html

大綱

  • 正則對象正則表達式

    • 生成正則對象
    • 可選項標記
    • 子表達式
    • 正則的test方法
    • 正則的compile方法
    • 正則的exec方法
  • 字符串的正則應用c#

    • 字符串的match方法
    • 字符串的replace方法
    • 字符串的search方法
    • 字符串的split方法

正則對象

生成正則對象

有兩種方法能夠建立並獲得一個正則表達式對象數組

  • 字面量聲明方式函數

    var reg = /abc/g;
  • 顯式建立code

    var reg =new RegExp("abc", "g");

可選項標記

上文生成正則對象中最後有用到g,其實這就是生成正則的可選項標記,能夠組合使用,以下regexp

  • g 全文匹配,即匹配一個成功後,若是沒有結束,會繼續匹配
  • i 忽略大小寫匹配
  • m 多行匹配

能夠經過以下示例進一步瞭解htm

/g的用法對象

加上/g後會全局搜索全部匹配結果blog

var str = 'abcabcabc';

// ['abc', index: 0, input: "abcabcabc"]
str.match(/abc/);

// ['abc', 'abc', 'abc']
str.match(/abc/g);

/i的用法

加上/i後大小寫一視同仁,不少時候,若是不加/i,很容易出現大小寫不匹配的錯誤(好比去除字符串中script標籤時)

var str = 'Script';

// null
str.match(/script/);

// ["Script", index: 0, input: "Script"]
str.match(/script/i);

/m的用法

多行匹配比較少用到,但在一些場景下不得不用,好比下例中,只有\m多行匹配的狀況下才能正常的將每一行的行尾(\n造成不一樣的行)的數字替換成#,不然默認會認爲只有一行

var str = 'a1\nb1\nc1\nd1\ne1\nf1';

/**
 * a1
 * b1
 * c1
 * d1
 * e1
 * f#
 */
str.replace(/\d+$/g, '#')

/**
 * a#
 * b#
 * c#
 * d#
 * e#
 * f#
 */
str.replace(/\d+$/mg, '#')

子表達式

正則表達式中,用圓括號包圍的就是子表達式(子模式)

通常,在match的非全局匹配中或exec中,在匹配完整個正則表達表達式後,都會再次匹配子表達式

另外,在字符串的replacesplit中,子表達式也會常常用到

var str = 'a1.b2.c3.d4';

// 第一個結果是 整個正則表達式的匹配,以後則分別是子表達式的匹配
/(\w)(\d)[.]/.exec(str); // ["a1.", "a", "1", index: 0, input: "a1.b2.c3.d4"]

正則的test()

pattern.test(str);

檢索字符串中是否存在指定模式,匹配成功則返回true,不然返回false

var str = 'abcdefg';

/^abc/.test(str); // true

/^abce/.test(str); // false

正則的compile()

reg.compile(pattern);

編譯正則表達式,編譯以後正則的執行速度會提升

編譯的時候也能夠改變檢索模式或者改變可選項標識

var str = 'abcdabcdabc';
var reg = /abc/;

reg.test(str); // true

reg.compile();

reg.test(str); // true,僅僅是被編譯,沒有被改變

reg.compile(/aB/); 

reg.test(str); // false,匹配式改爲了aB,所以不匹配

reg.compile(/aB/i); 

reg.test(str); // true,改爲了aB而且忽略大小的形式,所以匹配

正則的exec()

pattern.exec(str);

在字符串中檢索特定的模式,匹配成功則返回找到的值,不然返回null

有兩種狀況

第一種:非全局匹配

若是沒有找到,則返回null

找到則返回一個數組,arr[0]是匹配結果,餘下元素是arr[0]中匹配圓括號中子表達式的結果,以及最後的indexinput

並且非全局模式中,不會保存index,也就是說無論匹配多少次,結果都是同樣的

var str = 'a1.b2.c3.d4';
var reg1 = /(\w)(\d)[.]/;

reg1.exec(str); // ["a1.", "a", "1", index: 0, input: "a1.b2.c3.d4"]
reg1.exec(str); // ["a1.", "a", "1", index: 0, input: "a1.b2.c3.d4"]
reg1.exec(str); // ["a1.", "a", "1", index: 0, input: "a1.b2.c3.d4"]

/abc/.exec(str); // null

第二種:g全局匹配

正則的exec全局匹配能夠保存index,而且下一次繼續匹配時,將不會是從新從0開始,而是從保存的index開始

var str = 'a1.b2.c3.d4';
var reg2 = /(\w)(\d)[.]/g;

reg2.exec(str); // ["a1.", "a", "1", index: 0, input: "a1.b2.c3.d4"]
reg2.exec(str); // ["b2.", "b", "2", index: 3, input: "a1.b2.c3.d4"]
reg2.exec(str); // ["c3.", "c", "3", index: 6, input: "a1.b2.c3.d4"]

/abc/.exec(str); // null

字符串的正則應用

上文中提到的都是正則對象上的方法,但實際上,JSString對象也支持正則表達式

字符串的match()

match是字符串中最經常使用的方法

str.match(pattern);

若是pattern中有g,表明全局匹配,則返回的數組包含全部匹配結果

若是無g,則返回的數組的第1個元素(arr[0])是第一個匹配結果,餘下元素是arr[0]中匹配圓括號中子表達式的結果

var str = 'a.b2.c3.d445.e';

str.match(/\d[.]/); // ["2.", index: 3, input: "a.b2.c3.d445.e"]

// 非全局匹配下,而且有圓括號子表達式,先匹配整個正則表達式一次
// 而後在匹配結果中再匹配子表達式
str.match(/(\d)[.]/); // ["2.", "2", index: 3, input: "a.b2.c3.d445.e"]

// g 模式下是對整個正則表達式(包括圓括號子表達式)進行全局匹配
str.match(/(\d)[.]/g); // ["2.", "3.", "5."]

字符串的replace()

字符串中用來快速替換的方法,有多種用法

第一種狀況

str.replace(str1, str2);

第一個參數是字符串,那麼返回的結果只有str1被替換成str2

var str = 'a.b2.c3.d4';

// 只會替換 . 一次
str.replace('.', '#'); // a#b2.c3.d445.e

第二種狀況

str.replace(pattern, str2);

第一個參數是正則表達式,此時若是是g全局匹配模式,會替換全部的匹配結果爲str2,不然只會替換一個匹配結果

var str = 'a.b2.c3.d4';

str.replace(/[.]/, '#'); // a#b2.c3.d445.e

str.replace(/[.]/g, '#'); // a#b2#c3#d445#e

另外此模式下,str2還可使用一些有特殊含義的特殊字符,例如

var str = 'a1.b2.c3.d4';

// $2和$1分別表明第2個,第1個子表達式
str.replace(/(\w)(\d)[.]*/g, '$2$1~'); // 1a~2b~3c~4d~

str2中可用的特殊字符表

字符 替換
$1,$2,...,$99 匹配第1~99個pattern中的圓括號子表達式的文本
$& 匹配pattern的子串
$` 匹配子串的左邊文本
$' 匹配子串的右邊文本
$$ 美圓符號

第三種狀況

str.replace(pattern, func);

這種模式下,第二個參數爲一個函數,func將會在每個匹配結果中調用,func返回的字符串將做爲替換文本,func接收的參數,第一個是匹配pattern的字符串,以後的參數(多是多個)是匹配該pattern中某個圓括號子表達式的字符串,在這以後的參數就是index(匹配結果的位置),再以後就是完整的input

var str = a1.b2.c3.d4;

// 最終結果爲: 1a~2b~3c~4d~
str.replace(/(\w)(\d)[.]*/g, function(word, child1, child2, index, input) {
    
    console.log(word); // 依次打印的是a1. b2. c3. d4
    console.log(child1); // 依次打印的是a b c d
    console.log(child2); // 依次打印的是1 2 3 4
    console.log(index); // 依次打印的是0 3 6 9
    console.log(input); // 每次都是打印 a1.b2.c3.d4
    
    return child2 + child1 + '~';
});

字符串的search()

返回第1個與patten匹配的字符串子串的起始位置,若是找不到,則返回-1,不支持全局檢索,也就是說,會省略g

var str = 'abcdefg1234567';

str.search(/efg/); // 4
str.search(/efg/g); // 4
str.search(/aabc/g); // -1

字符串的split()

split方法可讓一個字符串分割成數組,一樣忽略g

str.split(pattern, limit); // pattern爲字符串或正則

str拆分爲子串組成的數組,子串中不包括pattern(特例除外)。limit是可選參數,指定返回的數組的最大長度

特例: 若是pattern包含圓括號子表達式,則匹配這個圓括號子表達式的子串(不是匹配整個正則)會包含在返回數組中

var str = 'a1.b2.c3.d4';

str.split(/\d[.]/); // ["a", "b", "c", "d4"]

// 包含了圓括號的子串,返回數組中出現了匹配圓括號的子串
str.split(/(\d)[.]/); // ["a", "1", "b", "2", "c", "3", "d4"]

var str2 = '.b2.c3.';

// 3.後面沒有字符了,可是因爲它符合匹配,因此後續結果中會多一個""
str2.split(/\d[.]/); // [".b", "c", ""]

// 同上,只不過圓括號中的內容也在返回結果中
str.split(/(\d)[.]/); // [".b", "2", "c", "3", ""]

附錄

博客

初次發佈2017.07.06於我的博客

http://www.dailichun.com/2017/07/15/regularExpressionBaseUsage.html

參考資料

相關文章
相關標籤/搜索