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