[JS高程]JavaScript中的RegExp對象

1. RegExp

ECMAScript 通過RegExp類型支持正則表達式。

1.1 表示格式:

let expression = /pattern/flags;
//or
let expression = new RegExp("pattern str","flags")// pattern str 不需要由"/.../"包裹,
  • pattern : 正則表達式;
  • flags : 匹配模式的標記;

示例:

let expression = /[bc]at/i;
//or
let expression = new RegExp("[bc]at","i"); // 注意構造函數的兩個參數都是String, 且無需`/`包裹

注意: 在通過構造函數來創建一個Pattern 的時候,第一個參數,除了可以傳入String, 還能直接傳入一個已有的Pattern , 此時,構造函數的第二個參數,即Flags 將會覆蓋第一個參數中攜帶的flags。 利用這個特點,可以實現Pattern 的複製 和 flags 的修改, 以下是一個示例:

const exp1 = /cat/g;
const exp2 = new RegExp(exp1,'i') //  /cat/i

1.2 匹配模式:

"Gimyus"

  • g : global , 全局匹配
  • i : ignore , 大小寫忽略
  • m : multiline , 多行匹配
  • y : sticky 粘附模式,表示從lastIndex開始查找
  • u : Unicode 模式, 啓用Unicode 匹配
  • s : dotAll 模式,匹配任何字符(包括\n或\r)

全局匹配和多行匹配有什麼區別?

可以理解爲,/m 通常是和/g 一起使用以增強匹配模式。 以下是一個示例:

hello my darling you
are so sweat
and hello my beauty
hello my lady
you are so kind
hello my heartbeat
you drum like a spring wind
  • 匹配模式 /^hello/g : 將會以整個字符串爲匹配對象,僅僅匹配中字符串首部的單個“hello” 子字符串。
  • 匹配模式 /^hello/gm:將會把每行自作單獨的匹配對象,將會匹配選中 1,4,6 行首的“hello” 子字符串,共三個。

unicode 模式,將會啓用Unicode 字符匹配的支持,以下是一個示例:

const sentence = 'A ticket to 大阪 costs ¥2000 👌.';

const regexpEmojiPresentation = /\p{Emoji_Presentation}/gu;
console.log(sentence.match(regexpEmojiPresentation));
// expected output: Array ["👌"]

dotAll 模式, 默認情況下,dot . 能夠匹配不包括 \n(換行),\r(光標回到行首),之外的任意字符。

當你所匹配的字符串中含有這兩個元字符時, 如果不開啓dotAll 模式,將不會被匹配到。 以下是一個示例:

MDN上有這樣一個demo:

var str1 = 'bar\nexample foo example';

var regex1 = new RegExp('bar.example','s');

console.log(regex1.dotAll); // Output: true

console.log(str1.replace(regex1,'')); // Output: foo example

var str2 = 'bar\nexample foo example';

var regex2 = new RegExp('bar.example');

console.log(regex2.dotAll); // Output: false

console.log(str2.replace(regex2,'')); // Output: bar
                                      //         example foo example

image-20211122191528475

1.3 RegExp 實例屬性

gimyus 匹配模式是否開啓,除了在創建實例對象時去指定,還可以通過RegExp 實例的屬性訪問,並且可以設定值,但是注意,dotAll 匹配模式除外, 它是一個只讀屬性。 你只能在創建一個RegExp 實例的時候去設定好它。

如:

let exp0 = /[bc]at/s
//or
let exp1 = new RegExp("[bc]at","s")
//or 如果有需要,你也可以直接複製拓展一個已有的實例
let exp2 = /[bc]at/
let exp22 = new RegExp(exp2,"s")

除了這些boolean 類型的屬性,還有三個屬性,分別是:

  1. source : 正則表達式的字面量字符串;
  2. flags : 正則表達式的模式標記字符串;
  3. lastIndex : 整數類型,記錄了在源字符串中下一次搜索的起始位置(後面會講到)
let exp0 = /[bc]at/sgm;
console.log(exp0.source);//"[bc]at"
console.log(exp0.flags);//"gms"

1.4 RegExp 實例方法

1.4.1 exec()

1.4.1.1 基本用法

exec() 主要用於配合捕獲組使用, 只接收一個參數,即要匹配的目標字符串。如果沒有匹配則返回null , 匹配則返回包含第一個匹配信息的數組。

RegExpPattern.exec("target string...")

⚠️ 注意: 該方法返回的數據類型雖然是一個數組, 但是它比較特殊, 它包含了兩個額外的屬性:

  1. index : 字符串中匹配模式的起始外置;
  2. input :要查找的字符串;

數組的第一個元素是匹配整個模式的字符串, 其他的元素是與表達式中的捕獲組匹配的子字符串。 如果模式中並沒有捕獲組的花,那麼數組值包含一個元素。 以下是一些示例:

不包含捕獲組的情況

let str = "I always love the moment you smile";let exp = /love the moment/;let result = exp.exec(str);// result["love the moment"]

實際上,還有剛纔說的幾個特殊屬性,如果你在console 臺查看 result :

image-20211122195056548

包含捕獲組的情況

let str = "I always love the moment you smile";let exp = /always (love (the moment (you)) smile)/;let result = exp.exec(str);// result[    "always love the moment you smile",    "love the moment you smile",    "the moment you",    "you"]

image-20211122195925150

1.4.1.2 exec()\g 匹配模式

且看這樣一個示例:

image-20211122200608818

當一個字符串中有多處被Pattern 所匹配時, 設定了/g 的匹配模式和 不設定時的結果存在差異。

即, 如果不設定\g ,那麼不論exec() 執行了多少次, 返回結果始終只會返回第一個匹配到的結果。 看起來,就像是,每次都是重新匹配, 且匹配到了一個結果之後就退出了 ,不做記錄。

而如果設定了/g , 那麼就會每次執行將會返回一個新的匹配到的 子串結果, 直到沒有匹配項,返回null 爲止, 看起來,就像是每次執行都記錄了下一次預將執行的索引值位置, 這個值實際上就是 RegExp的實例屬性lastIndex

image-20211123085726210

注意,直接結果爲null 之後,lastIndex 值被重新置0, 這意味着如果繼續執行exec() 方法,那麼會重新開始。

1.4.1.3 exec()\y 黏着匹配模式

如果你仔細觀察\g匹配模式,不難發現,該模式每次返回的lastindex 值 +1 後,就正好是下一個匹配字符的起始位置。 相當的“智能”。

\y 模式,則不同,它使得你在每次exec() 方法執行之前,都需要先明確下一個子串匹配的起始索引。並不會自動爲你更新 lastIndex值爲下一個匹配字符的正確位。

image-20211123105424080

首次匹配,將從index = 0 的位置匹配,但是匹配不到所以返回null, 且永遠不會將lastIndex 設定爲下一次正確匹配所在的位置, 但是可以手動指定正確的lastIndex 值,不過,這次匹配成功了,返回了正常的結果,而lastIndex 被刷新爲了下一個非空字符所在的索引值, 依舊不會是下一次正確匹配的索引,如果想要能匹配到,還是要手動指定其索引值 - -

是不是很無語 - - , 我都知道了匹配項所在位置,我還tm需要用你來幹啥?
這個模式很少會用,可能某些特殊情況下才有用吧,例如遍歷字符串,其不斷刷新lastIndex值 ?或者知道了索引位去取對應的匹配項?

image-20211123110607828

\g 匹配模式則完全不同, 每次匹配後都會刷新lastIndex 的值。

1.4.2 test()

Pattern.test("target string...")

test() 方法用於判斷某匹配Pattern 是否能夠匹配到目標內容。 返回一個布爾值。

示例 :

let str = "I always love the moment you smile";let exp = /love the moment/;exp.test(str); // truelet exp2 = /love the bala moment/;exp2.test(str); // false
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章