摘要:自從年推出標(biāo)準(zhǔn)第版以來(lái),正則表達(dá)式已成為語(yǔ)言的一部分。最后,如果在正則表達(dá)式中使用了命名捕獲組,則將它們放在屬性中。支持與相同語(yǔ)法的命名組已經(jīng)模仿了的正則表達(dá)式語(yǔ)法。下面是一個(gè)例子此正則表達(dá)式在句子中查找連續(xù)的重復(fù)單詞。
翻譯:瘋狂的技術(shù)宅
原文:https://www.smashingmagazine....
本文首發(fā)微信公眾號(hào):jingchengyideng
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章
摘要:如果你曾用 JavaScript 做過(guò)復(fù)雜的文本處理和操作,那么你將會(huì)對(duì) ES2018 中引入的新功能愛(ài)不釋手。 在本文中,我們將詳細(xì)介紹第 9 版標(biāo)準(zhǔn)如何提高 JavaScript 的文本處理能力。
有一個(gè)很好的理由能夠解釋為什么大多數(shù)編程語(yǔ)言都支持正則表達(dá)式:它們是用于處理文本的極其強(qiáng)大的工具。 通常一行正則表達(dá)式代碼就能完成需要幾十行代碼才能搞定的文本處理任務(wù)。 雖然大多數(shù)語(yǔ)言中的內(nèi)置函數(shù)足以對(duì)字符串進(jìn)行一般的搜索和替換操作,但更加復(fù)雜的操作(例如驗(yàn)證文本輸入)通常需要使用正則表達(dá)式。
自從 1999 年推出 ECMAScript 標(biāo)準(zhǔn)第 3 版以來(lái),正則表達(dá)式已成為 JavaScript 語(yǔ)言的一部分。ECMAScript 2018(簡(jiǎn)稱ES2018)是該標(biāo)準(zhǔn)的第 9 版,通過(guò)引入四個(gè)新功能進(jìn)一步提高了JavaScript的文本處理能力:
后行斷言
命名捕獲組
s (dotAll) flag
Unicode屬性轉(zhuǎn)義
下面詳細(xì)介紹這些新功能。
后行斷言能夠根據(jù)之后或之前的內(nèi)容匹配一系列字符,使你可以丟棄可能不需要的匹配。 當(dāng)你需要處理大字符串并且意外匹配的可能性很高時(shí),這個(gè)功能非常有用。 幸運(yùn)的是,大多數(shù)正則表達(dá)式都為此提供了 lookbehind 和 lookahead 斷言。
在 ES2018 之前,JavaScript 中只提供了先行斷言。 lookahead 允許你在一個(gè)斷言模式后緊跟另一個(gè)模式。
先行斷言有兩種版本:正向和負(fù)向。 正向先行斷言的語(yǔ)法是 (?=...)。 例如,正則表達(dá)式 /Item(?= 10)/ 僅在后面跟隨有一個(gè)空格和數(shù)字 10 的時(shí)候才與 Item 匹配:
const re = /Item(?= 10)/; console.log(re.exec("Item")); // → null console.log(re.exec("Item5")); // → null console.log(re.exec("Item 5")); // → null console.log(re.exec("Item 10")); // → ["Item", index: 0, input: "Item 10", groups: undefined]
此代碼使用 exec() 方法在字符串中搜索匹配項(xiàng)。 如果找到匹配項(xiàng), exec() 將返回一個(gè)數(shù)組,其中第一個(gè)元素是匹配的字符串。 數(shù)組的 index 屬性保存匹配字符串的索引, input 屬性保存搜索執(zhí)行的整個(gè)字符串。 最后,如果在正則表達(dá)式中使用了命名捕獲組,則將它們放在 groups 屬性中。 在代碼中, groups 的值為 undefined ,因?yàn)闆](méi)有被命名的捕獲組。
負(fù)向先行的構(gòu)造是 (?!...) 。 負(fù)向先行斷言的模式后面沒(méi)有特定的模式。 例如, /Red(?!head)/ 僅在其后不跟隨 head 時(shí)匹配 Red :
const re = /Red(?!head)/; console.log(re.exec("Redhead")); // → null console.log(re.exec("Redberry")); // → ["Red", index: 0, input: "Redberry", groups: undefined] console.log(re.exec("Redjay")); // → ["Red", index: 0, input: "Redjay", groups: undefined] console.log(re.exec("Red")); // → ["Red", index: 0, input: "Red", groups: undefined]
ES2018 為 JavaScript 補(bǔ)充了后行斷言。 用 (?<=...) 表示,后行斷言允許你在一個(gè)模式前面存在另一個(gè)模式時(shí)進(jìn)行匹配。
假設(shè)你需要以歐元檢索產(chǎn)品的價(jià)格但是不捕獲歐元符號(hào)。 通過(guò)后行斷言,會(huì)使這項(xiàng)任務(wù)變得更加簡(jiǎn)單:
const re = /(?<=€)d+(.d*)?/; console.log(re.exec("199")); // → null console.log(re.exec("$199")); // → null console.log(re.exec("€199")); // → ["199", undefined, index: 1, input: "€199", groups: undefined]
注意:先行(Lookahead)和后行(lookbehind)斷言通常被稱為“環(huán)視”(lookarounds)。
后行斷言的反向版本由 (? 表示,使你能夠匹配不在lookbehind中指定的模式之前的模式。 例如,正則表達(dá)式 /(? 會(huì)在 三個(gè)數(shù)字不在它之前 匹配單詞“meters”如果:
const re = /(?與前行斷言一樣,你可以連續(xù)使用多個(gè)后行斷言(負(fù)向或正向)來(lái)創(chuàng)建更復(fù)雜的模式。下面是一個(gè)例子:
const re = /(?<=d{2})(?此正則表達(dá)式僅匹配包含“meters”的字符串,如果它前面緊跟 35 之外的任何兩個(gè)數(shù)字。正向后行確保模式前面有兩個(gè)數(shù)字,同時(shí)負(fù)向后行能夠確保該數(shù)字不是 35。
命名捕獲組你可以通過(guò)將字符封裝在括號(hào)中的方式對(duì)正則表達(dá)式的一部分進(jìn)行分組。 這可以允許你將規(guī)則限制為模式的一部分或在整個(gè)組中應(yīng)用量詞。 此外你可以通過(guò)括號(hào)來(lái)提取匹配值并進(jìn)行進(jìn)一步處理。
下列代碼給出了如何在字符串中查找?guī)в?.jpg 并提取文件名的示例:
const re = /(w+).jpg/; const str = "File name: cat.jpg"; const match = re.exec(str); const fileName = match[1]; // The second element in the resulting array holds the portion of the string that parentheses matched console.log(match); // → ["cat.jpg", "cat", index: 11, input: "File name: cat.jpg", groups: undefined] console.log(fileName); // → cat在更復(fù)雜的模式中,使用數(shù)字引用組只會(huì)使本身就已經(jīng)很神秘的正則表達(dá)式的語(yǔ)法更加混亂。 例如,假設(shè)你要匹配日期。 由于在某些國(guó)家和地區(qū)會(huì)交換日期和月份的位置,因此會(huì)弄不清楚究竟哪個(gè)組指的是月份,哪個(gè)組指的是日期:
const re = /(d{4})-(d{2})-(d{2})/; const match = re.exec("2020-03-04"); console.log(match[0]); // → 2020-03-04 console.log(match[1]); // → 2020 console.log(match[2]); // → 03 console.log(match[3]); // → 04ES2018針對(duì)此問(wèn)題的解決方案名為捕獲組,它使用更具表現(xiàn)力的 (?
...) 形式的語(yǔ)法:const re = /(?d{4})-(? d{2})-(? d{2})/; const match = re.exec("2020-03-04"); console.log(match.groups); // → {year: "2020", month: "03", day: "04"} console.log(match.groups.year); // → 2020 console.log(match.groups.month); // → 03 console.log(match.groups.day); // → 04 因?yàn)樯傻膶?duì)象可能會(huì)包含與命名組同名的屬性,所以所有命名組都在名為 groups 的多帶帶對(duì)象下定義。
許多新的和傳統(tǒng)的編程語(yǔ)言中都存在類似的結(jié)構(gòu)。 例如Python對(duì)命名組使用 (?P
) 語(yǔ)法。 Perl支持與 JavaScript 相同語(yǔ)法的命名組( JavaScript 已經(jīng)模仿了 Perl 的正則表達(dá)式語(yǔ)法)。 Java也使用與Perl相同的語(yǔ)法。除了能夠通過(guò) groups 對(duì)象訪問(wèn)命名組之外,你還可以用編號(hào)引用訪問(wèn)組—— 類似于常規(guī)捕獲組:
const re = /(?d{4})-(? d{2})-(? d{2})/; const match = re.exec("2020-03-04"); console.log(match[0]); // → 2020-03-04 console.log(match[1]); // → 2020 console.log(match[2]); // → 03 console.log(match[3]); // → 04 新語(yǔ)法也適用于解構(gòu)賦值:
const re = /(?d{4})-(? d{2})-(? d{2})/; const [match, year, month, day] = re.exec("2020-03-04"); console.log(match); // → 2020-03-04 console.log(year); // → 2020 console.log(month); // → 03 console.log(day); // → 04 即使正則表達(dá)式中不存在命名組,也始終創(chuàng)建 groups 對(duì)象:
const re = /d+/; const match = re.exec("123"); console.log("groups" in match); // → true如果可選的命名組不參與匹配,則 groups 對(duì)象仍將具有命名組的屬性,但該屬性的值為 undefined:
const re = /d+(?st|nd|rd|th)?/; let match = re.exec("2nd"); console.log("ordinal" in match.groups); // → true console.log(match.groups.ordinal); // → nd match = re.exec("2"); console.log("ordinal" in match.groups); // → true console.log(match.groups.ordinal); // → undefined 你可以稍后在模式中引用常規(guī)捕獲的組,并使用 1 的形式進(jìn)行反向引用。 例如以下代碼使用在行中匹配兩個(gè)字母的捕獲組,然后在模式中調(diào)用它:
console.log(/(ww)1/.test("abab")); // → true // if the last two letters are not the same // as the first two, the match will fail console.log(/(ww)1/.test("abcd")); // → false要在模式中稍后調(diào)用命名捕獲組,可以使用 /k
/ 語(yǔ)法。 下面是一個(gè)例子:const re = /(?w+)s+k /; const match = re.exec("I"m not lazy, I"m on on energy saving mode"); console.log(match.index); // → 18 console.log(match[0]); // → on on 此正則表達(dá)式在句子中查找連續(xù)的重復(fù)單詞。 如果你愿意,還可以用帶編號(hào)的后引用來(lái)調(diào)用命名的捕獲組:
const re = /(?w+)s+1/; const match = re.exec("I"m not lazy, I"m on on energy saving mode"); console.log(match.index); // → 18 console.log(match[0]); // → on on 也可以同時(shí)使用帶編號(hào)的后引用和命名后向引用:
const re = /(?d):1:k /; const match = re.exec("5:5:5"); console.log(match[0]); // → 5:5:5 與編號(hào)的捕獲組類似,可以將命名的捕獲組插入到 replace() 方法的替換值中。 為此,你需要用到 $
構(gòu)造。 例如: const str = "War & Peace"; console.log(str.replace(/(War) & (Peace)/, "$2 & $1")); // → Peace & War console.log(str.replace(/(?War) & (? Peace)/, "$ & $ ")); // → Peace & War 如果要使用函數(shù)執(zhí)行替換,則可以引用命名組,方法與引用編號(hào)組的方式相同。 第一個(gè)捕獲組的值將作為函數(shù)的第二個(gè)參數(shù)提供,第二個(gè)捕獲組的值將作為第三個(gè)參數(shù)提供:
const str = "War & Peace"; const result = str.replace(/(?s (dotAll) FlagWar) & (? Peace)/, function(match, group1, group2, offset, string) { return group2 + " & " + group1; }); console.log(result); // → Peace & War 默認(rèn)情況下,正則表達(dá)式模式中的點(diǎn) (.) 元字符匹配除換行符 ( ) 和回車符 ( )之外的所有字符:
console.log(/./.test(" ")); // → false console.log(/./.test(" ")); // → false盡管有這個(gè)缺點(diǎn),JavaScript 開(kāi)發(fā)者仍然可以通過(guò)使用兩個(gè)相反的速記字符類來(lái)匹配所有字符,例如[ w W],它告訴正則表達(dá)式引擎匹配一個(gè)字符(w)或非單詞字符(W):
console.log(/[wW]/.test(" ")); // → true console.log(/[wW]/.test(" ")); // → trueES2018旨在通過(guò)引入 s (dotAll) 標(biāo)志來(lái)解決這個(gè)問(wèn)題。 設(shè)置此標(biāo)志后,它會(huì)更改點(diǎn) (.)元字符的行為以匹配換行符:
console.log(/./s.test(" ")); // → true console.log(/./s.test(" ")); // → trues 標(biāo)志可以在每個(gè)正則表達(dá)式的基礎(chǔ)上使用,因此不會(huì)破壞依賴于點(diǎn)元字符的舊行為的現(xiàn)有模式。 除了 JavaScript 之外, s 標(biāo)志還可用于許多其他語(yǔ)言,如 Perl 和 PHP。
Unicode 屬性轉(zhuǎn)義ES2015中引入的新功能包括Unicode感知。 但是即使設(shè)置了 u 標(biāo)志,速記字符類仍然無(wú)法匹配Unicode字符。
請(qǐng)考慮以下案例:
const str = "
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101825.html
摘要:雖然正則中可以匹配任何字符,但卻無(wú)法匹配換行符。精讀文中列舉的四個(gè)新特性是加入到正則中的。討論地址是精讀正則如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。 1. 引言 本周精讀的文章是 regexp-features-regular-expressions。 這篇文章介紹了 ES2018 正則支持的幾個(gè)重要特性: Lookbehind assertions - 后行...
摘要:規(guī)范最終由敲定。提案由至少一名成員倡導(dǎo)的正式提案文件,該文件包括事例。箭頭函數(shù)這是中最令人激動(dòng)的特性之一。數(shù)組拷貝等同于展開(kāi)語(yǔ)法和行為一致執(zhí)行的都是淺拷貝只遍歷一層。不使用對(duì)象中必須包含屬性和值,顯得非常冗余。 ES全稱ECMAScript,ECMAScript是ECMA制定的標(biāo)準(zhǔn)化腳本語(yǔ)言。目前JavaScript使用的ECMAScript版本為ECMA-417。關(guān)于ECMA的最新資訊可以...
摘要:為了使程序員能夠一次一個(gè)地處理集合中的元素,引入了迭代器接口。迭代器使用該方法獲取對(duì)象屬性名稱的數(shù)組,然后將其分配給常量。迭代器的缺點(diǎn)是它們不適合表示異步數(shù)據(jù)源。每次循環(huán)時(shí),都會(huì)調(diào)用迭代器的方法,它返回一個(gè)。 前言 原文地址:https://css-tricks.com/new-es2018-features-every-javascript-developer-should-kno...
摘要:是正則表達(dá)式的構(gòu)造函數(shù)。使用構(gòu)造函數(shù)一般用于需要?jiǎng)討B(tài)構(gòu)造正則表達(dá)式的場(chǎng)景,性能不如字面量寫(xiě)法。它接受一個(gè)正則表達(dá)式作為唯一參數(shù)??偨Y(jié)以上所述是小編給大家介紹的一篇文章搞懂正則表達(dá)式之方法的相關(guān)知識(shí),希望對(duì)大家有所幫助 通過(guò)本文帶領(lǐng)大家學(xué)習(xí)JavaScript中都有哪些操作正則的方法。本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧 咱們來(lái)看看JavaScript中都...
摘要:是正則表達(dá)式的構(gòu)造函數(shù)。使用構(gòu)造函數(shù)一般用于需要?jiǎng)討B(tài)構(gòu)造正則表達(dá)式的場(chǎng)景,性能不如字面量寫(xiě)法。它接受一個(gè)正則表達(dá)式作為唯一參數(shù)。總結(jié)以上所述是小編給大家介紹的一篇文章搞懂正則表達(dá)式之方法的相關(guān)知識(shí),希望對(duì)大家有所幫助 通過(guò)本文帶領(lǐng)大家學(xué)習(xí)JavaScript中都有哪些操作正則的方法。本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧 咱們來(lái)看看JavaScript中都...
閱讀 3025·2021-11-22 12:06
閱讀 605·2021-09-03 10:29
閱讀 6559·2021-09-02 09:52
閱讀 2024·2019-08-30 15:52
閱讀 3420·2019-08-29 16:39
閱讀 1198·2019-08-29 15:35
閱讀 2071·2019-08-29 15:17
閱讀 1427·2019-08-29 11:17