一文搞懂正則表達式

2024年2月6日 14点热度 0人点赞

在日常的開發工作中,正則表達式猶如空氣般無所不在,扮演著不可或缺的角色。我們時常依賴正則來解決各類問題,例如精準定位符合特定規則的文本。然而,我註意到許多開發者對正則持有“復雜難記”的觀念,難以全面掌握這一強大的工具,以至於每當在實際工作中遇到需要運用正則表達式的情況時,往往不得不翻閱資料才能編寫出合適的正則。

正則表達式作為一種無比強大的工具,無疑值得我們在開發過程中深入學習並熟練運用。它能幫助我們高效解決各類復雜問題,顯著提升工作效率,從而讓我們的編程之旅更加得心應手,遊刃有餘。

什麼是正則表達式

你可以這樣來理解正則是一個非常強大的文本處理工具,我們可以利用它來教驗數據的有效性,比如用戶輸入的手機號是不是符合規則;另外,也可以用正則從文本中提取需要的內容,比如從網頁中抽取我們需要的數據;此外,正則還可以用來做文本內容的替換從而得到我們想要的內容,可以說正則已經滲透到了我們日常工作的方方面面,不難發現學習並利用好正則至關重要。

怎麼理解正則表達式呢?簡單來說它就是描述字符串的規則,最簡單的正則就是單個的普通字符,比如字 a 它可以匹配 Hanmeimei is a girl 中的 H 之後的 a 也可以匹配 is 之後的 a,這個和我們日常見到的普通的字符串查找其實是一樣的。

除了剛剛說的普通的字符串的查找之外,有時候我們還需要查找符合某個規則的文本;比如我們想找出字符串中所有的數字,而任意數字在正則中可以用 \d 來表示,它表示 0~9 這十個數字。

單個的 \d 隻能表示一個數字我們如果在後面加上量詞,比如 \d{11} 這樣的話就表示 11 位數字。我們的手機號就是 11 位的,如果文本中隻有姓名和手機號,我們就可以用這個提取出裡面的手機號。

正則不僅僅能找出符合要求的文本,還可以對文本進行替換。比如說我們有這樣一段文本 the cat cat is in the the hat.,我們想要從文本中找出重復的單詞把它統一替換成一個單詞,最終的結果就是 the cat is in the hat.,可以發現正則在日常工作中使用非常廣泛也非常重要。

原字符

正則表達式中其實有很多的原字符,比如 \d,它在正則中不代表反斜杠和字母 d 而是代表任意的數字,所謂的原字符就是指正則表達式中具有特殊含義的那些專用的字符,正則表達式中原字符非常多那麼我們如何才能記住它們呢?在這裡給我給大傢介紹一個方法就是分類記憶。

我們可以把原字符大概的分成這麼幾類,有基礎常用的、特殊的空白符、表示某個范圍的、表示邊界的、表示次數的量詞;原字符雖然非常的多但如果我們按照分類去理解記憶,效果就會好很多。接下來我們就按照前面說的原字符的分類來逐一的進行講解。

基礎的原字符

首先非常常用的基礎的原字符,比如英文的點它表示換行以外的任意字符,\d 表示任意的數字,\w 表示任意的數字字母或者下滑線,而 \s 表示任意的空白符,另外還有與之對應的 \D、\W 和 \S 分別表示著和原來相反的意思。

特殊的空白符

接著我們來看一下空白符有哪些,其實我們在編程中經常會遇到比如說換行符 \n TAB 制表符 \t 等,有編程經驗的同學應該知道在每行文本的結束的位置都有換行,那麼不同的系統會稍有區別比如說像 Windows 系統是 \r\n,Linux 和 MacOS 是 是\n,那麼在正則中這些空白符也是類似的隻要記住它們就行,平時使用正則大部分場景我們使用\s 就可以滿足需求。

表示數量的原字符

剛剛我們說到的基礎的原字符也好,空白符也好,它們都隻能匹配單個字符比如說 \d 隻能匹配一個數字,有時候我們需要匹配單個字符或某個部分來重復 N 次或者至少出現一次或者最多出現三次這樣,這就需要我們來用到表示量次的原字符。

在正則中英文的 * 它代表出現 0 到多次 表示出現 1 到多次 ? 表示 0 到 1 次,而 {m,n} 可以表示 m 到 n 次。

就比如說由於業務需要我們在日制中添加了 user 這樣一個字段,但舊日志可能是沒有這個字段的;這個時候我們可以使用 ? 來表示它出現 0 次或 1 次,在這裡就可以表示 User 這個字段存在和不存在兩種情況。

范圍原字符

學習到了量詞我們就可以使用 /d{11} 來匹配所有的手機號,但是我們要明白這個范圍比較大有一些不是手機號的也能匹配上,比如說 11 個 0 這個時候我們就需要在這一個特殊的范圍內進行查找我們符合我們要求的數字。

管道符號它是隔開多個正則來表示滿足其中任意一個就行,比如 ab|bc 它能匹配上 ab 也能匹配上 bc;中括號它可以代表多選一可以表示中括號裡面任意單個字符,所以任意的元音字母我們就可以用 [aeiou] 來表示;另外中括號中我們可以用 - 來表示范圍比如說 [a-z] 可以表示所有的小寫字母;如果中括號中的第一個是脫字符(^)它可以表示非,那麼就表示不能出現裡面的任何一個單個元素。

知道了這些我們就可以輕松搞定前面的問題,手機號的匹配可以這樣優化第二位可能 是3~9 那麼我們可以寫成 [3456789] 或者寫成中 [3-9 或者是我們用 [^012] 也就是說把 012 排除掉。

邊界原字符

前面我們學習了如何匹配文本中包含的內容,但是有時候我們除了要找出符合某種組成規則的字符外還對匹配到的文本的位置有要求,比如說某個日志文件我們需要找出每行以時間開頭的日志。這裡要使用的正則不僅要滿足時間的格式要求,它還要滿足匹配道美行的開頭才行,這時我們就需要用到邊界相關的原字符了。

和剛才說到的中括號中的脫字符不同,如果正則中開始是脫字符,它表示每行開頭的部分隻有滿足正則的規則的前提下才能夠匹配上;類似的正則中有美元的符號 $ 表示匹配行的結束;而 \b 來表示匹配的單詞的邊界;\A 和 \Z 它匹配整個字符串的開始和結束而不是每行的首尾;與 \A 不同的是脫字符可以匹配任意行的開頭而不是整個文本的開頭。

貪婪和非貪婪

接著我們來看一下正則中的貪婪與非貪婪,正則表達式中表示次數的量詞默認是貪心的;也就是說它盡可能的多的去匹配符合要求的內容 ,舉個例子來說我們要找出引號裡面的單詞;可能很多同學很容易寫出 . 這樣的正則。

但這樣對嗎?如果有多個雙引號的時候是不會正常工作的,因為表示次數的量詞默認是貪心的,它要盡可能多的去匹配符合要求的內容 ,不過想要讓它變成非貪婪也很容易我們隻需要在量詞後面加上問號就可以了。

從示例中可以看出對比上的差異左右的文本是一樣的,其中有兩對雙引號不同之處在於,圖的左邊不加問號時是貪婪匹配,可以看到匹配上了第一個引號到最後一個引號之間的所有的內容;而右邊這個圖它表示 1 到多次,加號後面有一個問號,結果就找到了符合要求的並且長度是最短的,這就是進行了非貪婪的匹配。

環視

當我們對想要的提取的字符串的左邊或者是右邊的環境有要求的時候,比如說我們要查找左邊是數字的字母,這個時候我們需要用到正則的環視,簡單的說環視就是在我們給定的規則前或者是規則後來加一些限制。

下圖就是利用環視來提取出左邊是標簽右邊是標簽的字符。

子組

我們再來了解一下正則中的子組,它的功能是將正則分成若幹個小組用擴號來擴起來,那麼將正則保存成一個子組。子組可以用來表示某個部分的內容在後面重復出現或者是對某個部分的內容進行替換。另外,正則匹配的時候我們還可以指定 flag,比如用點可以匹配所有字符,包括換行多行的匹配模式或者是大小寫不敏感的匹配模式。

案例實踐

我們回到今天開頭提出的問題也就是如何將文本中重復出現的單詞替換成單個單詞。在這裡我們可以分成兩步來操作,首先我們需要查找出相關的內容然後再對其進行替換。

我們來先看一下查找部分,我們可以簡單的用 w 來表示一個單詞,把它用擴號擴起來意思就是保存成了一個子組;這是我們寫正則中的第一個子組。然後我們在空格之後用 \1,它的意思就是前面的子組再重復出現一次,這樣的話我們就找到了前面出現的單詞後面又再重復出現一次相鄰的兩個單詞。

在替換部分我們使用 \1 來表示正則中第一個子組,也就是說找到的是什麼單詞我們這裡就把它替換成什麼單詞;然後可以看到最終的結果那裡 cat 和 the 重復的已經移除。這樣的話我們就完成了移除重復單詞的工作,到這裡我們就解決了開頭我們提出的問題。

那麼除了工作中我們能使用到正則在生活中其實我們也可以用正則來做一些非常有趣的事情,這裡我引入一個案例比如說我們來用正則來幫助我們下載電視劇。用正則來提取出電視劇對應的網址,首先我們可以使用 chrome 或者 firefox 等瀏覽器在百度中搜索相應的電視劇的名字。

然後我們單擊右鍵審核元素或者檢查,然後獲取到每一集電視劇的鏈接的 html 代碼,接下來通過找出規律我們就可以寫出一個能匹配上所有電視劇網址的這樣的正則,然後可以點擊查找所有。

最後把查找的內容剪切出來,把剪切出來的內容粘貼到一個新的地方,通過替換等方式我們可以在這些網址的開頭都加上 you-get 命令

u-get 命令它是一個資源下載的工具,這個工具需要自己去安裝才可以使用,最後我們在 sell 上執行這些命令就可以下載這部電視劇了。

總結

最後我來給你總結一下,正則表達式中原字符的分類記憶,大傢可以在腦海中回憶一下,基礎常用的、空白符、范圍、邊界、量詞等;子組則是將一個正則中的部分內容進行分組常常用於內容的替換;而貪婪和非貪婪其實就是量詞後面添加問號,去改變匹配次數的偏好;環視則是限制匹配內容之前或之後要符合某個規則。

今天通過大量的示例讓你加強了對正則各類原字符,貪婪與非貪婪,環視等方面的理解,掌握了這些內容相信你就能夠掌握日常工作中的一些基本使用了。