TRY REGEX:正則表達(dá)式交互式入門教程 翻譯&解答

TRY REGEX 是一個(gè)交互式的正則表達(dá)式學(xué)習(xí)項(xiàng)目
項(xiàng)目地址:https://github.com/callumacrae/tryregex
在線地址:http://tryregex.com/
翻譯版在線:http://www.rakuhi.com/tryregex-cn/
很適合正則表達(dá)式初學(xué)者學(xué)習(xí)、練習(xí)
總共28個(gè)小課程,從零基礎(chǔ)入門到能完成大多數(shù)正則表達(dá)式書寫。

個(gè)人做了 翻譯&解答,有問題之處歡迎指正


翻譯

第一課 正則表達(dá)式入門

本交互課程意在介紹正則表達(dá)式,更明確的說是JavaScript下的正則表達(dá)式。課程當(dāng)然也會(huì)教您用其他語言寫正則表達(dá)式,但是您應(yīng)該知道它們是有區(qū)別的。
左側(cè)的控制臺(tái)就是一個(gè)JavaScript控制臺(tái)。請(qǐng)使用 <code>setName('Your name')</code> (Your name替換為您的名字)命令設(shè)置您的姓名來開始課程。
還有一些有用的命令:執(zhí)行 <code>help()</code> 來查看它們

第二課 什么是正則表達(dá)式?

正則表達(dá)式(也寫作 regex 或 regexp)是一個(gè)用來描述搜索模式的字符串——類似星號(hào)(*)文件名匹配通配符,但更加有效(當(dāng)然也更加復(fù)雜)。
我們將會(huì)從一個(gè)非?;A(chǔ)的例子開始,來讓您掌握 JavaScript 中語法和正則表達(dá)式的使用。
<code>bio</code>是一個(gè)不知道是否包含您名字的變量。為了看看結(jié)果,請(qǐng)輸入 <code>bio.match(/{{ firstEscaped }}/);</code>。

第三課 包含!

從上個(gè)例子中您可以得知一些事情。第一,用于定義正則表達(dá)式的語法:使用兩個(gè)斜杠包含表達(dá)式:
<code>/表達(dá)式/</code>
如果您將它輸入控制臺(tái),將會(huì)返回正則表達(dá)式。
第二,您可以對(duì)字符串使用 <code>.match()</code> 方法來測試正則表達(dá)式。還有一些其他方法可以調(diào)用:您可以直接對(duì)正則表達(dá)式使用 <code>.exec()</code> 方法來對(duì)執(zhí)行一個(gè)字符串。請(qǐng)輸入 <code>/{{ firstEscaped }}/.exec(bio)</code>。

第四課 簡單測試

<code>.exec()</code> 方法和 <code>.match()</code> 方法做的是同樣的事情,但它是對(duì)表達(dá)式調(diào)用而不是對(duì)字符串——這會(huì)很有用。
另一個(gè)可用的是 <code>.test()</code> 方法 ——可能是這些方法中最簡單的 。類似于 <code>.exec()</code> ,但返回的是布爾值。試一試吧!
提示:左側(cè)控制臺(tái)可以使用向上鍵來獲取之前輸入的表達(dá)式。

第五課 字符串替換

我們會(huì)用到的最后一個(gè)方法是 <code>.replace()</code> ,用一個(gè)字符串替換另一個(gè)字符串的方法。輸入一下內(nèi)容來將 <code>bio</code> 變量中您的名字隱藏:
<code>bio.replace(/{{ firstEscaped }}/, '[redacted]')</code>

第六課 特殊字符

我們迄今為止用過的表達(dá)式都不是特別有趣,也沒有包含特殊字符。以下這些字符在正則表達(dá)式中應(yīng)該被轉(zhuǎn)義:
<code>$()*+.?[^|]</code>
為了規(guī)避它們,使用反斜杠轉(zhuǎn)義,例如 <code>/what?/</code> 。
寫一個(gè)正則表達(dá)式來測試 <code>num</code> 變量中是否包含字符串“3.5”。

第七課 點(diǎn)運(yùn)算符

是不包含的!<code>num</code> 的值是 123456,它不包含字符串“3.5”。
在正則表達(dá)式中點(diǎn)運(yùn)算符有特殊的含義:它將匹配除了換行符以外的所有的單個(gè)字符(所以 <code>/a.c/</code> 將會(huì)匹配 "abc", "a c", "a$c" 等等)。未轉(zhuǎn)義點(diǎn)運(yùn)算符直接使用 <code>/3.5/</code> 將可能匹配到 <code>num</code> 中字符串,這里點(diǎn)運(yùn)算符將會(huì)匹配 4。
試試吧。

第八課 量詞

有一些“量詞”可以用來表達(dá)某個(gè)東西需要被匹配多少次。第一個(gè)量詞是問號(hào),作用是讓前置項(xiàng)(一個(gè)字符或字符組)可選(即出現(xiàn)0次或1次)。
表達(dá)式 <code>/regexp?/</code> 將會(huì)匹配 "regex" 和 "regexp",問號(hào)讓 p(只是p)可選。
寫一個(gè)表達(dá)式同時(shí)能匹配"frontend" 和 "front-end",答案通過 <code>answer()</code> 函數(shù)傳參(例子:<code>answer(/表達(dá)式/)</code>)。

第九課 加號(hào)

我們要學(xué)習(xí)的下一個(gè)量詞是加號(hào)。它的意思是“一個(gè)或更多前置項(xiàng)”;<code>/Princes+/</code> 會(huì)匹配 "Princes", "Princess", "Princesssss" 等等。但不會(huì)匹配"Prince"。
您要寫的下一個(gè)表達(dá)式將會(huì)有點(diǎn)復(fù)雜。寫一個(gè)正則表達(dá)式,抽取出 <code>shortStory</code> 變量(可輸入 <code>shortStory</code> 查看變量內(nèi)容)中左右括號(hào)間的所有內(nèi)容(包含括號(hào))。提示:需要用到剛才說過的點(diǎn)運(yùn)算符。

第十課 星號(hào)

星號(hào)和加號(hào)類似;但是不同于“一個(gè)或更多”,星號(hào)的含義是“零個(gè)或更多的前置項(xiàng)”。/Princes*/ 在 <code>/Princes+/</code> 匹配內(nèi)容的基礎(chǔ)上還能匹配 "Prince" 。
重復(fù)上一個(gè)例子,用星號(hào)替換加號(hào)。抽取出 <code>shortStory</code> 變量中左右括號(hào)間的所有內(nèi)容,即便括號(hào)內(nèi)沒有內(nèi)容。

第十一課 限制重復(fù)次數(shù)

有一個(gè)量詞可以用來限制重復(fù)次數(shù)。語法是 <code>{min,max}</code> 其中 min 是最小出現(xiàn)次數(shù),max 是最大出現(xiàn)次數(shù)。比如 <code>/a{3,5}/</code> 會(huì)且只會(huì)匹配 "aaa", "aaaa" 和 "aaaaa"。
寫一個(gè)表達(dá)式匹配 <code>bracketNumbers</code> 中左右圓括號(hào)中間長度為5~8之間的字符。

第十二課 限制重復(fù)次數(shù)進(jìn)階

為了進(jìn)一步明確重復(fù)次數(shù)范圍,您可以用<code>{n}</code>指明確定的一個(gè)重復(fù)次數(shù),其中 n 是重復(fù)次數(shù)。比如表達(dá)式 <code>a{6}</code> 只會(huì)匹配重復(fù)的六個(gè) a。
在使用大括號(hào)時(shí),您可以不指定最大重復(fù)個(gè)數(shù),只留下最小重復(fù)個(gè)數(shù)。比如,<code>/a{5,}/</code> 會(huì)匹配5個(gè)或更多次重復(fù)的字母 a。
用 <code>answer()</code> 函數(shù)給出不使用 ?*+ 字符,但和 /a?b+c*/ 等價(jià)的正則表達(dá)式。

第十三課 標(biāo)志——不區(qū)分大小寫標(biāo)志

標(biāo)志用來改變正則表達(dá)式的表達(dá)形式,位于表達(dá)式的后面(例子:<code>/表達(dá)式/ig</code>)。每個(gè)標(biāo)志用一個(gè)字母表示,JavaScript 支持四種標(biāo)志——有兩種將會(huì)在本課程中學(xué)到。<code>i</code> 標(biāo)志讓表達(dá)式不區(qū)分大小寫——在沒有這個(gè)標(biāo)志時(shí) <code>/a/</code> 只會(huì)匹配“a”,不會(huì)匹配“A”;<code>/a/i</code> 則會(huì)同時(shí)匹配“a”和“A”。
執(zhí)行 <code>/CAT/i.exec('Category')</code> 來看看 i 標(biāo)志的作用。

第十四課 標(biāo)志——全局匹配標(biāo)志

第二個(gè)常用的標(biāo)志是全局匹配標(biāo)志,用字母 <code>g</code> 表示。 <code>/a/</code> 只會(huì)匹配字符串中第一個(gè) a, <code>/a/g</code> 則會(huì)匹配每一個(gè)單個(gè)的字母 a。
寫一個(gè)正則表達(dá)式,來用字母 “e” 替換 <code>shortStory</code> 里所有的字母 “a”。
您可以使用字符串的 <code>.replace(expr, replace)</code> 方法來做替換。

第十五課 字符組

字符組允許您指定一組或一個(gè)范圍的字符去匹配。<code>/[aeiou]/</code> 匹配任意元音字母,<code>/[a-m]/</code> 匹配任意字母表前半部分的字母,<code>/[aeiou0-9]/</code> 匹配任意元音字母或數(shù)字。
注意在字符組中,您不需要轉(zhuǎn)義點(diǎn)字符,它將被直接匹配。如果您要使用連字符(-),則需要轉(zhuǎn)義。
我們定義合法的用戶名包含5到12個(gè)字母(大寫字母或小寫字母)或連字符。寫一段代碼,在 <code>username</code> 合法時(shí)返回 true。

第十六課 否定字符組

否定字符組將會(huì)匹配不在字符組內(nèi)的字符。您可以在字符組前添加一個(gè)脫字號(hào)(^)來否定它。比如 <code>/[^a-m]/</code> 將匹配“z” 、“$”,但是不會(huì)匹配“c”。
弄清楚 “非 [a-m]” 和 “不在 [a-m] 范圍” 的區(qū)別很重要,<code>/c[^a]t/</code> 將匹配 “cut”,但不會(huì)匹配 “cat” 和 “ct” ——這個(gè)非常重要。
現(xiàn)在合法的用戶名可以包含任何非空格字符(但同樣長度在 5 到 12 之間)。寫出一個(gè)正則表達(dá)式來檢驗(yàn) <code>username</code> 合法性。

第十七課 類型字符

類型字符可以用作常見字符組的簡略表達(dá)。有6種類型字符:<code>\d</code> 匹配十進(jìn)制數(shù)字(0-9),<code>\s</code> 匹配空格, <code>\w</code> 匹配單詞字符(單詞字 —— Unicode字符集、數(shù)字、下劃線)。
另外三個(gè)可用的類型字符是將上面三個(gè)改成大寫字母,就起到了否定它們的效果;比如 <code>\S</code> 匹配所有非空格字符。
寫一個(gè)正則表達(dá)式,能匹配一個(gè)后綴一個(gè)空格一串?dāng)?shù)字的單詞。用 <code>charTypeTest</code> 測試:不要使用任何文字字符。

第十八課 定位符

如果您想確保字符串以某種確定字(字符集)的開始或結(jié)束——比如,您希望包裝字符串以大寫字母開始——那么你就可以使用錨點(diǎn)。美元符號(hào)($)匹配字符串結(jié)尾,脫字符()匹配字符串開始。<code>/cat$/</code> 將只會(huì)匹配到 “cat” 而不匹配其他任何字符串(<code>/cat/</code> 會(huì)匹配任何包含 “cat” 的字符串)。
寫一個(gè)正則表達(dá)式來測試 <code>possibleUrl</code> 變量是否以 “http://” 或 “https://” 開始,且從頭到尾不包含任何空格。
提示:需要用到問號(hào)、否定字符集。您可能會(huì)需要兩種錨點(diǎn)。

第十九課 捕獲組

您可以使用圓括號(hào)來創(chuàng)建組,可以將多項(xiàng)組合起來或者保存結(jié)果以供之后引用:
<code>/"(.+)"/</code>
上面就是一個(gè)捕獲組的示例,意思是圓括號(hào)內(nèi)匹配到的字符串將被保存在 <code>.match()</code> 或 <code>.exec()</code> 返回的數(shù)組中。
回頭看看之前我們用表達(dá)式 <code>/(.{5,8})/.exec(shorterStory)</code> 抓取兩個(gè)圓括號(hào)之間的數(shù)據(jù)的例子。嘗試用圓括號(hào)包住 <code>.{5,8}</code> 重新運(yùn)行一下。

第二十課 非捕獲組

您可以看到現(xiàn)在返回?cái)?shù)組有個(gè)兩項(xiàng):第一項(xiàng)是全部匹配內(nèi)容,第二項(xiàng)只包含捕獲組匹配數(shù)據(jù)。
還有一種組類型叫做非捕獲組。這種組語法上稍有不同,它不在數(shù)組內(nèi)存儲(chǔ)直。如果不需要引用組,您可能傾向使用非捕獲組:它會(huì)保持返回?cái)?shù)組的純凈。上一個(gè)例子中,添加 <code>?:</code> 在組的開始點(diǎn)運(yùn)算符之前,將表達(dá)式變成非捕獲組。

第二十一課 量詞

和我們zhi'q沒有用組幾乎一樣。
非捕獲組的主要用途是給一個(gè)組賦予量詞。下面的表達(dá)式將會(huì)匹配 “I ate” 和 Carrot and I ate” 不會(huì)匹配其他內(nèi)容:
<code>/^(?:{{ firstEscaped }} and )?I ate$/</code>
寫一個(gè)表達(dá)式,能夠匹配 “ha” 出現(xiàn)兩次或更多的字符串 (例如:“haha” 或 “hahahahaha”),用 <code>answer()</code> 函數(shù)給出答案。
提示:您的表達(dá)式不應(yīng)該匹配 “hahah”。使用錨點(diǎn)來保證這一點(diǎn)。

第二十二課 管道符號(hào)

您可以使用管道符號(hào)(|)來指定“或”關(guān)系。下面的表達(dá)式將匹配 “The dog ate” 和 “The cat ate”:
<code>/The (dog|cat) ate/</code>
您也可以使用非捕獲組,但是在這個(gè)例子中我們希望獲取結(jié)果。您可以在一個(gè)組內(nèi)用任意多個(gè)管道符號(hào)。讓上面的表達(dá)式在保持原有匹配的基礎(chǔ)上也能夠匹配 “The rabbit ate” (帶匹配串在 <code>rabbit</code> 變量中)。

第二十三課 反向引用

在同一個(gè)表達(dá)式中,您可以引用之前捕獲到的值。只需簡單的寫成反斜杠后跟著捕獲組數(shù)字(它在返回字符串里的索引值)。比如,下面的表達(dá)式將匹配 “The cat ate with the other cat” 和 “The dog ate with the other dog”,但不會(huì)匹配 “The cat ate with the other dog”(當(dāng)然,這本身就挺奇怪的):
<code>/The (dog|cat) ate with the other \1/</code>
寫一個(gè)表達(dá)式,能夠匹配同一行內(nèi)兩個(gè)相同的單詞(比如:“hello hello world”):和之前的例子一樣,用 <code>answer()</code> 函數(shù)給出答案。

第二十四課 RegExp對(duì)象

除了文字運(yùn)算符(斜杠),JavaScript 還提供 RegExp 構(gòu)造器,允許您使用字符串去指定需要的表達(dá)式。這個(gè)對(duì)于將變量放在表達(dá)式中非常有用。它的使用方法如下:

// Same as /regexp?/ig
new RegExp('regexp?', 'ig');

用戶名同樣包含在變量中。 <code>userData</code> 變量包含用戶信息:把它打印在控制臺(tái)中來查看數(shù)據(jù)格式。使用 <code>username</code> 變量去抽取該用戶的關(guān)聯(lián)詞。為了能夠正確驗(yàn)證,請(qǐng)把答案寫在同一行。

第二十五課 高級(jí)替換

我們已經(jīng)知道了兩種捕獲組使用捕獲值得方法:第一種是返回?cái)?shù)組,第二種是反向引用。您也可以在 <code>.replace()</code> 方法的第二個(gè)參數(shù)中獲取它:

var text = '*italic text*';
var replace = '<em>$1</em>';
text.replace(/\*([^*]+)\*/, replace);

寫一個(gè)類似上面的代碼,將 <code>boldText</code> 變量替換成 <code><strong></code> 元素。

第二十六課 懶惰 vs 貪婪 匹配

JavaScript 默認(rèn)的匹配模式是 “貪婪”,也就是說匹配盡可能多個(gè):
<code>'"Hi", "Hello"'.match(/".+"/)</code>
上面的表達(dá)式將會(huì)返回 <code>"Hi", "Hello"</code> ,它匹配了兩個(gè)雙引號(hào)間內(nèi)容。懶惰匹配則和貪婪匹配相反,它會(huì)匹配盡可能少的——所以這個(gè)例子中,只會(huì)匹配 <code>"Hi"</code>。
通過在量詞后面加上問號(hào)來實(shí)現(xiàn)懶惰匹配——用上面的例子試試吧。

第二十七課 斷言

斷言是一個(gè)應(yīng)該被匹配但不會(huì)被存儲(chǔ)的模式:不是 “匹配a然后匹配b” ,而是 “匹配后面連著b的a,但是不匹配b”。在 JavaScript 中有兩種斷言類型,肯定先行斷言 和 否定先行斷言?!跋刃小?就是說向前查找;JavaScript 不支持 “后行”(向后查找)。
肯定先行斷言表示我們想向前查找a的匹配。為了查找a b連接,我們可以使用 <code>/a(?=b)/</code>。
使用斷言來從 <code>partialSums</code> 中取出 “6+3”。不要使用任何數(shù)字符號(hào),用 <code>\d</code>。

第二十八課 否定斷言

斷言也可以是否定的,所以我們可以匹配不連接在某項(xiàng)后的字符串。注意和字符組不同的是,它可以匹配到一些不一樣的——如果你說 “后面不連著b的a”,a可以在字符串的末尾。
否定斷言的語法和肯定斷言的語法類似,但用感嘆號(hào)(!)替換等號(hào):比如,<code>/a(?!b)/</code> 會(huì)匹配后面不是字母 b 的字母 a。
用一個(gè)肯定斷言接一個(gè)否定斷言來提取 <code>partialSums</code> 中的 “3+3”。

您完成了課程!

恭喜您,完成了 Try Regex 的課程。您基本上掌握了 JavaScript 中正則表達(dá)式的大部分內(nèi)容,現(xiàn)在您可以寫出適用于大多數(shù)場景的正則表達(dá)式了。
下面這些是延伸閱讀內(nèi)容(不可用鏈接已替換):


解答

正則表達(dá)式的有趣之處就在于,對(duì)于同一個(gè)問題于有多種不同的寫法。下面給出的解答有些只是正確寫法中一種,僅供參考。自己思考自己嘗試才能真正掌握正則表達(dá)式。

第一課 正則表達(dá)式入門

第二課 什么是正則表達(dá)式?

第三課 包含!

第四課 簡單測試

第五課 字符串替換

第六課 特殊字符

第七課 點(diǎn)運(yùn)算符

第八課 量詞

第九課 加號(hào)

第十課 星號(hào)

第十一課 限制重復(fù)次數(shù)

第十二課 限制重復(fù)次數(shù)進(jìn)階

第十三課 標(biāo)志——不區(qū)分大小寫標(biāo)志

第十四課 標(biāo)志——全局匹配標(biāo)志

第十五課 字符組

第十六課 否定字符組

第十七課 類型字符

第十八課 定位符

第十九課 捕獲組

第二十課 非捕獲組

第二十一課 量詞

第二十二課 管道符號(hào)

第二十三課 反向引用

第二十四課 RegExp對(duì)象

第二十五課 高級(jí)替換

第二十六課 懶惰 vs 貪婪 匹配

第二十七課 斷言

第二十八課 否定斷言

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容