實踐正則表達式的多種使用方式

前言

正則,毋庸置疑,是一個無比強大的工具。若是仔細留意,咱們能夠在源代碼(各類語言)、編輯器、開發者工具、命令行等地方看到正則的身影。學習使用正則,不只有趣,也是提高工做效率的一條捷徑。html

基礎概念

正則的經常使用概念能夠參考下表,主要熟記字符類型、錨點、轉義字符、量詞等。前端

基礎用法相信你們都很快理解,如下主要介紹各類正則斷言。node

斷言

斷言的實用性至關於給一段正則表達式提供了一個錨點,筆者在平常工做實踐中,使用頻率較高。react

正先行斷言

模式:x(?=y)git

匹配出 x 表達式,但 x 後面必須跟着 y 表達式。github

負先行斷言

模式:x(?!y)正則表達式

匹配出 x 表達式,但 x 後面不能跟着 y 表達式。express

正後發斷言

模式:(?<=y)xnpm

至關明顯,匹配出 x 表達式,但 x 前必須出現 y 表達式。數組

負後發斷言

模式:(?<!y)x

至關明顯,匹配出 x 表達式,但 x 前不能出現 y 表達式。

\1

\1 其實就是上一個匹配到分組引用。

好比我要在 I like JJLin and Huahua~ 中匹配 Huahua,如圖:

固然如下方式也可達成:

  1. 使用量詞 + 或 *

  2. 或者用全局搜索標誌 g

  3. 使用範圍 {2}

不過,雖然條條大路通羅馬,但仍是須要注意匹配的 hua 數量。好比方法 一、2 都會盡量多的匹配。

使用正則

JavaScript 中的 RegExp 對象

exec 方法

exec() 方法在一個指定字符串中執行一個搜索匹配。返回一個結果數組或 null。

/(?<=appear\s)(\w+)[^\d]+(\d+)/g.exec("apple yummy, appear angel id 1030"); // => ["angel id 1030", "angel", "1030", index: 20, input: "apple yummy, appear angel id 1030", groups: undefined] 複製代碼

能夠看出數組第一項爲匹配的所有字符串。接下來展現了匹配到的分組(\w+) -> angel,(\d+) -> 1030。

固然筆者我的以爲 exec 最容易踩坑的點:當 exec 方法使用 "g" 標誌時,能夠屢次執行 exec 方法來查找同一個字符串中的成功匹配。

改寫以上例子,咱們將正則存爲一個變量:

const regexAngelAndId = /(?<=appear\s)(\w+)[^\d]+(\d+)/g;

regexAngelAndId.exec("apple yummy, appear angel id 1030");
// => ["angel id 1030", "angel", "1030", index: 20, input: "apple yummy, appear angel id 1030", groups: undefined]
regexAngelAndId.lastIndex;
// => 33
regexAngelAndId.exec("apple yummy, appear angel id 1030");
// => null
regexAngelAndId.lastIndex;
// => 0
複製代碼

能夠看到。當咱們存爲一個正則字面量時,查找將從該正則表達式的 lastIndex 屬性指定的位置開始。(test() 也會更新 lastIndex 屬性)。所以第二次就再也找不到相同的值了,結果天然而然爲 null。

使用 exec 時,務必仍是留意這一點。

test 方法

test() 方法執行一個檢索,用來查看正則表達式與指定的字符串是否匹配。返回 true 或 false。

const regexAngelAndId = /(?<=appear\s)(\w+)[^\d]+(\d+)/g;

regexAngelAndId.test("apple yummy, appear angel id 1030");
// => true
regexAngelAndId.lastIndex;
// => 33
regexAngelAndId.test("apple yummy, appear angel id 1030");
// => false
regexAngelAndId.lastIndex;
// => 0
複製代碼

一樣和 exec 方法須要留意 "g" 標誌,再也不贅述。

上述兩個方法在 JavaScript 中很經常使用,務必牢記。

正則表達式靜態屬性

  • RegExp.$1-$9
  • RegExp.input ($_)
  • RegExp.lastMatch ($&)
  • RegExp.lastParen ($+)
  • RegExp.leftContext ($`)

如下都是正則對象上的靜態屬性,通常來講使用頻率不大(或者我沒發現?),具體使用方法可參考 MDN 文檔 - RegExp

固然還有不少其餘方法以及屬性,均可自查文檔。

JavaScript 中的 String 對象

在字符串對象上使用正則也是十分常見的操做。你們可能知道 replace、match 方法能夠用正則,可是日常還有 search、split,甚至很新鮮出爐的 matchAll 方法均可以幫助咱們更好的在字符串上使用正則。

這裏比較有趣的是 matchAll 方法,這個方法的出現完美的取代了用 Regexp.exec()方法循環匹配信息。

使用 matchAll 會獲得一個迭代器的返回值,可使用 for...of, 擴展運算符, 或者 Array.from() 來進行取值。十分便利。

關於這些 API 最好的學習方式,可參考文檔:MDN 文檔 - String

編輯器

在咱們的 vscode 裏也有正則的用武之地!

好比說咱們須要全局查找文件中 console.error 的值,並將其替換。就可使用如下操做。(普通的文本查找可作不到這種姿式)

前提是要勾選使用正則的選項(紅色箭頭所指處)

或者單個文件查找替換也是能夠的。

瀏覽器

在咱們熟悉的瀏覽器中,可使用正則來篩選網絡請求。

固然若是存在極大量日誌的狀況下,正則也能夠幫助咱們快速定位某項日誌。

固然控制檯 source 面板身爲一個編輯器,也確定少不了正則查找的功能。

命令行

這裏主要介紹命令行中最經常使用的文本處理工具 grep。(除此以外還有 sed、awk)。grep 全名爲"Global search Regular Expression and Print out the line"。

見名思義,grep 能夠與正則結合進行文本匹配。

假設咱們有文本以下:

$ cat tinytext
apple yummy
appear angle
and wisper: "ANGLE"
複製代碼

咱們想要匹配 angle 單詞的行

$ grep "angle" tinytext
appear angle
複製代碼

成功!

若是咱們想要忽略大小寫敏感,能夠加上 "-i" 或者 "--ignore-case" 選項。(默認 grep 是大小寫敏感)。

$ grep -i "angle" tinytext
appear angle
and wisper: "ANGLE"
複製代碼

許多時候,咱們並不想匹配行,而想匹配關鍵字,此時能夠加上 "-o" 或則 "--only-matching" 選項。

$ grep -io "angle" tinytext
angle
ANGLE
複製代碼

以上咱們都只是普通文本匹配,grep 支持基本正則表達式,咱們可使用 "-E" 或者 」"--extended-regexp" 選項使用擴展正則表達式。

好比咱們想匹配出 yummy 前的單詞,我稍微一考慮,就寫出如下規則:匹配至少大於一個 a-z 字符組成的,而且後面必須跟着一個空格及 yummy 的一個單詞。

$ grep -oE "[a-z]+(?=\syummy)" tinytext
grep: repetition-operator operand invalid
複製代碼

可是,不幸的發現失敗了。通過一番查找,發現 grep 默認不支持 "?=" 操做符。可是不要急,在 mac 系統中能夠經過如下命令升級咱們的工具箱。

$ brew insall grep
...
...
All commands have been installed with the prefix "g".
複製代碼

因而咱們得到了 ggrep 這個工具,而後能夠加上 "-P" 或者 "--perl-regexp" 使用兼容 Perl 的正則引擎(得以支持 "?=" 等操做符)。

$ ggrep -oP "[a-z]+(?=\syummy)" tinytext
apple
複製代碼

成功了!

相信常常用命令行處理工具的同窗都會承認 grep 的實用性(前端同窗可能比較陌生,可是建議學習)

匹配 ifconfig 中的 ip 地址

筆者有個困擾,常常開發項目的時候須要知道本身筆記本的 ip 地址。這時候我會敲入 ifconfig 而後肉眼一頓搜索,每次都得浪費幾秒,才能找到 ip 地址。

此時 grep 命令發揮了做用

$ ifconfig | ggrep -oP "(?<=inet\s)\d{1,3}(\.\d{1,3}){3}"
127.0.0.1
192.168.31.254
複製代碼

成功獲取到 ip 地址。可是 127.0.0.1 咱們其實並不須要。咱們能夠加上選項 "-v" 或者 "--invert-match" 反向排除掉本地 ip。

$ ifconfig | ggrep -oP "(?<=inet\s)\d{1,3}(\.\d{1,3}){3}" | ggrep -vP "127[\d\.]+"
172.20.10.13
複製代碼

噌噌噌!簡簡單單~咱們能夠將以上命令配置爲 bash 別名 alias get-ip='...',這裏不詳細介紹。我以前的博客有提到。

$ get-ip
192.168.31.254
複製代碼

匹配對應端口的 node 應用程序進程 PID

好比咱們須要尋找端口 8001 的 node 應用程序進程 PID。

咱們經過命令 lsof -i tcp:8001

$ lsof -i tcp:8001
COMMAND   PID        USER   FD   TYPE            DEVICE SIZE/OFF NODE NAME
node    87701 yanguangjie   23u  IPv6 0x42c450e30b40bcb      0t0  TCP *:vcom-tunnel (LISTEN)
複製代碼

使用 grep 匹配出 node 應用程序 PID。

$ lsof -i tcp:8001 | ggrep -oP "(?:node[^\d]+)\d+(?=\s)" | egrep -o "\d+"
87701
複製代碼

要問匹配 PID 出來有什麼用?固然是強制殺掉它了!

$ kill -9 $(lsof -i tcp:8001 | ggrep -oP "(?:node[^\d]+)\d+(?=\s)" | egrep -o "\d+")
複製代碼

固然若是以爲以上方式略顯麻煩的同窗,能夠基於以上腳本寫個工具,減小重複工做。

這裏筆者寫了一個簡易的工具 k-port,若感興趣的同窗能夠去看看以及使用。

$ npm install -g k-port
$ k-port 8001,8003
total ports: [ '8001', '8003' ]

get PID 2152 by port: 8001
kill PID 2152 ok.
get PID 2164 by port: 8003
kill PID 2164 ok.
複製代碼

尋找npm包的全部指定版本

快速過濾出 react 的全部 alpha 版本。

$ npm view react versions | ggrep -oP "[^\s]+alpha[^\s]+"
複製代碼

小結

到此爲止,也只是比較膚淺的介紹了一下有限的,我知道的正則的各類使用方式,固然~因此歡迎你們補充。正則是實踐性極強的一門工具,或者說是藝術也不爲過。多上手練習和使用。

感謝閱讀~

參考資料

相關文章
相關標籤/搜索