我一直喜歡Linux終端的一件事是使用正則表達式可以實現的目標。 無論我們需要查找複雜的文本還是將其替換為其他文本,使用正則表達式都可以大大簡化工作。 讓我們從頭開始:
什麼是正則表達式?
正則表達式是一系列特殊字符,它們使我們能夠描述我們要查找的文本。 例如,如果我們要搜索“ linux”一詞,將其放入我們正在使用的程序中就足夠了。 這個詞本身是一個正則表達式。 到目前為止,這似乎非常簡單,但是如果我們想在某個文件中查找所有數字怎麼辦? 還是所有以大寫字母開頭的行? 在那種情況下,您再也不能簡單地說了。 解決方案是使用正則表達式。
正則表達式與文件模式。
在討論正則表達式這一主題之前,我想消除對正則表達式的常見誤解。 正則表達式不是我們在rm,cp等命令中作為參數來引用硬盤上各種文件的內容。 那將是一個文件模式。 正則表達式儘管相似,因為它們使用一些公共字符,但它們有所不同。 對硬盤上的文件觸發文件模式並返回與模式完全匹配的文件,而對文本觸發正則表達式並返回包含搜索到的文本的行。 例如,對應於模式的正則表達式 *.*
就像 ^.*\..*$
正則表達式的類型。
並非所有程序都使用相同的正則表達式。 不多。 或多或少有幾種標準類型的正則表達式,但是有些程序會稍微改變語法,包括它們自己的擴展名,甚至使用完全不同的字符。 因此,當您想對不熟悉的程序使用正則表達式時,要做的第一件事是查看程序的手冊或文檔,以了解其可以識別的正則表達式。
首先,正則表達式有兩種主要類型,它們包含在POSIX標準中,這是Linux工具使用的。 它們是基本和擴展的正則表達式。 使用正則表達式的許多命令(例如grep或sed)都可以使用這兩種類型。 我將在下面談論它們。 也有PERL樣式的正則表達式,然後還有諸如vim或emacs之類的程序使用它們的變體。 根據我們要執行的操作,使用其中一個可能更合適。
測試正則表達式。
正則表達式的語法一點都不瑣碎。 當我們不得不編寫一個複雜的正則表達式時,我們將面對一眼無法理解的特殊字符,因此,要學習如何使用它們,必須有一種方法來進行我們想要並看到的所有測試結果容易。 這就是為什麼我現在要放置幾個命令,以便可以進行測試和實驗所需的一切,直到以正則表達式為主導。
第一個是grep命令。 這是我們最常用於搜索的命令。 語法如下:
grep [-E] 'REGEX' FICHERO
COMANDO | grep [-E] 'REGEX'
我建議始終將正則表達式放在單引號中,以使外殼程序不適應它。 第一種方法是在文件中查找正則表達式。 第二個允許通過正則表達式過濾命令的輸出。 默認情況下,grep使用基本正則表達式。 -E選項用於使用擴展的正則表達式。
可以幫助我們了解正則表達式如何工作的一個技巧是在grep命令中啟用color的使用。 這樣,與我們使用的正則表達式匹配的文本部分將突出顯示。 要在grep命令中激活顏色,只需確保環境變量 GREP_OPTIONS
包含價值 --color
,可以使用以下命令完成:
GREP_OPTIONS=--color
我們可以將其放在.bashrc中以使其始終處於激活狀態。
使用正則表達式的另一種方法是使用sed命令。 這更適合替換文本,但也可以用於搜索。 語法如下:
sed -n[r] '/REGEX/p' FICHERO
COMANDO | sed -n[r] '/REGEX/p'
缺省情況下,sed命令還使用基本正則表達式,可以將擴展正則表達式與-r選項一起使用。
我也想命名的另一個命令是awk。 此命令可用於許多用途,因為它允許您使用自己的編程語言編寫腳本。 如果我們想要在文件或命令的輸出中找到正則表達式,則使用它的方式如下:
awk '/REGEX/' FICHERO
COMANDO | awk '/REGEX/'
此命令始終使用擴展的正則表達式。
為了進行測試,我們還需要一個文本作為搜索示例。 我們可以使用以下文本:
- Lista de páginas wiki: ArchLinux: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ - Fechas de lanzamiento: Arch Linux: 11-03-2002 Gentoo: 31/03/2002 CentOs: 14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu: 20/10/2004 Desde Linux Rulez.
這是本文其餘部分中將用於示例的文本,因此,我建議您將其複製到文件中,以方便終端使用。 您可以輸入所需的名稱。 我稱它為正則表達式。
開始上課。
現在,我們擁有開始測試正則表達式所需的一切。 讓我們一點一點走。 我將舉幾個帶有正則表達式的搜索示例,在這些示例中,我將解釋每個字符的作用。 它們不是很好的例子,但是由於我將要發表一篇很長的文章,所以我不想再复雜化了。 我只是想簡單介紹一下正則表達式可以完成的工作。
最簡單的就是搜索一個特定的單詞,例如,假設我們要搜索包含單詞“ Linux”的所有行。 這是最簡單的,因為我們只需要寫:
grep 'Linux' regex
我們可以看到結果:
拱Linux:https://wiki.archlinux.org/ Arch Linux:11年03月2002日來自 Linux Rulez。
這是包含單詞“ Linux”的三行,如果使用了顏色技巧,它們將突出顯示。 請注意,即使它是“ ArchLinux”中更長的單詞的一部分,它也可以識別我們正在尋找的單詞。 但是,它不會突出顯示URL“ https://wiki.archlinux.org/”中出現的單詞“ linux”。 那是因為它在那里以小寫字母“ l”出現,而我們一直在尋找大寫字母。 grep命令具有用於此的選項,但我不會在有關正則表達式的文章中討論它們。
通過這個簡單的測試,我們可以得出第一個結論:
- 放在正則表達式中的普通字符會與自己匹配。
也就是說,如果您輸入字母“ a”,它將尋找字母“ a”。 看來合乎邏輯,對吧? 🙂
現在假設我們要搜索單詞“ CentO”,後跟任何字符,但只有一個字符。 為此,我們可以使用“。”字符,這是一個與任何字符匹配的通配符,但只能匹配一個:
grep 'CentO.' regex
結果是:
CentOS的:http://wiki.centos.org/ 中心: 14-05-2004 03:32:38
這意味著它在“ CentOS”中包含“ S”,儘管在一種情況下為大寫,在另一種情況下為小寫。 如果在該位置出現了其他任何字符,也將包括該字符。 我們已經有了第二條規則:
- 人物 ”。” 匹配任何字符。
它不再像看起來那樣瑣碎,但是以此我們不能做太多事情。 讓我們更進一步。 假設我們要查找2002和2004年出現的行,它們看起來像是兩次搜索,但是可以像這樣一次完成:
grep '200[24]' regex
這意味著我們要找到數字200,後跟2或4。結果是:
Arch Linux:11-03-2002 Gentoo:31/03 /2002 中心:14-05-2004 03:32:38 Ubuntu: 20/10/2004
這將我們帶到第三條規則:
- 括號內的多個字符與括號內的任何字符匹配。
括號給了更多的發揮。 它們也可以用於排除字符。 例如,假設我們要搜索出現“:”字符但不跟“ /”的站點。 該命令將如下所示:
grep ':[^/]' regex
只需將“ ^”作為括號中的第一個字符即可。 您可以將所有想要的字符放在下面。 最後一條命令的結果如下:
ArchLinux的: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ Arch Linux: 11年03月2002日Gentoo: 31年03月2002日CentO: 14-05,2004 03:32:38 Debian: 16年08月1993日Ubuntu: 20/10/2004
現在,突出顯示發行版名稱後面的“:”,但突出顯示了URL中的名稱,因為URL後面帶有“ /”。
- 將“ ^”字符放在方括號的開頭可匹配除方括號中的其他字符以外的任何字符。
我們可以做的另一件事是指定字符範圍。 例如,要搜索後跟“-”的任何數字,它將看起來像這樣:
grep '[0-9]-' regex
這樣,我們指定了一個介於0到9之間的字符,然後是一個負號。 讓我們看一下結果:
Arch Linux:11-03-2002個CentO:1個4-05-2004 03:32:38
可以在方括號內指定多個範圍,甚至可以混合使用單個字符的範圍。
- 在方括號中放置兩個用“-”分隔的字符會匹配範圍內的任何字符。
現在讓我們看看是否可以選擇URL的第一部分。 說“ http”或“ https”的那個。 它們僅在最後的“ s”中有所不同,因此我們如下進行操作:
grep -E 'https?' regex
問號用於使字符左側成為可選字符。 但是現在我們在命令中添加了-E選項。 這是因為詢問是擴展正則表達式的功能。 到目前為止,我們正在使用基本的正則表達式,因此我們不需要放入任何內容。 讓我們看一下結果:
ArchLinux: HTTPS://wiki.archlinux.org/ Gentoo: HTTPS://wiki.gentoo.org/wiki/Main_Page CentOS: HTTP://wiki.centos.org/ Debian: HTTPS://wiki.debian.org/ Ubuntu: HTTPS://wiki.ubuntu.com/
因此,我們已經有了一條新規則:
- 字符後跟“?” 匹配該字符或不匹配。 這僅對擴展的正則表達式有效。
現在我們要尋找兩個完全不同的詞。 讓我們看看如何查找同時包含單詞“ Debian”和“ Ubuntu”的行。
grep -E 'Debian|Ubuntu' regex
使用豎線,我們可以分隔兩個或多個不同的正則表達式,並查找與它們中的任何一個匹配的行:
Debian:https://wiki.debian.org/ Ubuntu:https://wiki.ubuntu.com/ Debian16 / 08 / 1993 Ubuntu20 / 10 / 2004
- 字符«|» 用於分隔多個正則表達式並匹配其中任何一個。 它也特定於擴展的正則表達式。
讓我們繼續。 現在,我們將尋找單詞“ Linux”,但僅在不粘在左側另一個單詞的地方。 我們可以這樣做:
grep '\
這裡的重要字符是“ <”,但是需要通過在其前面加上“ \”來使其轉義,以便grep將其解釋為特殊字符。 結果如下:
拱 Linux:11年03月2002日來自 Linux Rulez。
您也可以使用“ \>”搜索彼此相鄰的單詞。 讓我們來看一個例子。 讓我們嘗試以下命令:
grep 'http\>' regex
它產生的輸出是這樣的:
CentOS的: HTTP://wiki.centos.org/
出現了“ Http”,但沒有出現“ https”,因為在“ https”中,“ p”右邊仍然有一個字符,可以作為單詞的一部分。
- 字符“ <”和“>”分別與單詞的開頭和結尾匹配。 這些字符必須轉義,以便不被解釋為文字字符。
我們處理的事情要復雜一些。 “ +”字符與其左側的字符匹配,至少重複一次。 該字符僅在擴展的正則表達式中可用。 有了它,我們可以找到例如以“:”開頭的連續多個數字的序列。
grep -E ':[0-9]+' regex
結果:
中心:14年05月2004日03:32:38
數字38也被突出顯示,因為它也以“:”開頭。
- “ +”字符與其左側的字符匹配,至少重複一次。
您也可以使用“ {”和“}”控制重複次數。 想法是在括號中加上一個數字,該數字指示我們想要的確切重複次數。 您還可以放置一個範圍。 讓我們看看這兩種情況的例子。
首先,我們將找到所有四位數的序列:
grep '[0-9]\{4\}' regex
請注意,如果使用基本正則表達式,則必須將花括號轉義,但如果使用擴展正則表達式,則不能轉義。 擴展後將是這樣的:
grep -E '[0-9]{4}' regex
兩種情況的結果都是這樣的:
Arch Linux:11-03-2002 Gentoo:31/03 /2002 中心:14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu的:20/10 /2004
- 字符“ {”和“}”之間的數字與重複指定次數的前一個字符相匹配。
現在是帶有括號的另一個示例。 假設我們要查找包含3到6個小寫字母的單詞。 我們可以執行以下操作:
grep '[a-z]\{3,6\}' regex
結果將是這樣的:
-LISTA de 頁s 維基: 至RCHL操作系統: HTTPS:/ /維基.ArchLinux的.組織結構/ G恩圖: HTTPS:/ /維基.巴布亞.組織結構/維基/M艾因_P年齡 C 操作系統: HTTP:/ /維基.CentOS的.組織結構/ D埃比安: HTTPS:/ /維基.Debian的.組織結構/ 要么本圖: HTTPS:/ /維基.Ubuntu的.,/ - F你想念 de 發布: 至RCH L操作系統:11年03月2002日G恩圖:31年03月2002日C Os: 14-05-2004 03:32:38 D埃比安:16年08月1993日本圖:20年10月2004日D它是 L操作系統 R烏列茲.
如您所見,這看起來與我們想要的不一樣。 這是因為正則表達式會在更長的其他單詞中找到字母。 讓我們嘗試其他版本:
grep '\<[a-z]\{3,6\}\>' regex
結果:
-頁面清單 維基:ArchLinux: HTTPS:/ /維基.archlinux。組織結構/ Gentoo: HTTPS:/ /維基.巴布亞.組織結構/維基/ Main_Page CentOS: HTTP:/ /維基.CentOS的.組織結構/ Debian: HTTPS:/ /維基.Debian的.組織結構/ Ubuntu: HTTPS:/ /維基.Ubuntu的.,/
這看起來已經更像我們想要的了。 我們要做的是要求單詞在第一個字母之前開始,而在最後一個字母之後結束。
- 字符“ {”和“}”之間有兩個數字,中間用逗號隔開,該字符與前一個字符重複的次數由兩個數字指示。
現在讓我們看一下以“ +”開頭的字符。 它是“ *”,其操作非常相似,只不過它匹配任意數量的字符,包括零。 也就是說,它的作用與“ +”相同,但不需要字符左側出現在文本中。 例如,讓我們嘗試尋找那些以Wiki開始並以org結尾的地址:
grep 'wiki.*org' regex
讓我們看一下結果:
ArchLinux:https://wiki.archlinux.org/ Gentoo:https://wiki.gentoo.org/ wiki / Main_Page CentOS:http://wiki.centos.org/ Debian:https://wiki.debian.org/
PERFECTO。
現在,我們要看到的最後一個字符。 “ \”字符用於使字符向右轉義,從而失去其特殊含義。 例如:假設我們要定位以點結尾的線。 我們可能發生的第一件事可能是:
grep '.$' regex
結果不是我們想要的:
-維基頁面列表: ArchLinux:https://wiki.archlinux.org/ Gentoo:https://wiki.gentoo.org/wiki/Main_Page CentOS:http://wiki.centos.org/ Debian:https://wiki.debian.org/ Ubuntu的:https://wiki.ubuntu.com/ -發布日期:Arch Linux:11年03月200日2 Gentoo:31/03/2002 CentOs: 14-05-2004 03:32:38 Debian:16/08/1993 Ubuntu的:20/10/2004 Desde Linux 魯茲.
這是因為“。” 它匹配任何內容,因此正則表達式匹配每行的最後一個字符,無論它是什麼。 解決方法是這樣的:
grep '\.$' regex
現在的結果就是我們想要的:
Desde Linux 魯茲.
遊戲結束
儘管正則表達式的主題是如此復雜,以至於我會寫一系列文章,但我想我已經給您帶來了很多痛苦。 如果您成功到達,那麼恭喜您。 而且,如果您一次坐下來都閱讀了所有這些內容,請服用阿司匹林或其他藥物,因為那可能不好。
現在就這些。 如果您喜歡這篇文章,也許我可以寫另一篇。 同時,建議您嘗試終端中的所有正則表達式,以清楚地了解它們的工作方式。 請記住:只有Chuck Norris才能使用正則表達式解析HTML。
沒有正則表達式,我們的生活會怎樣?
這篇文章非常有用,但是我會一點一點地閱讀它。 非常感謝。
感謝您的評論。 我仍然不相信我的文章已經發表。 🙂它出現了一些錯誤,但我希望它是有用的。 🙂
謝謝youssssssss!..
一段時間以前,我不得不學習一些有關正則表達式的知識....感謝您的教學..以及有關逐步學習每一種表達式的逐步指南。
很好!...我要買阿司匹林..ee
別客氣。 勇氣,正則表達式不能與您同在。 🙂
很棒的帖子! 很好。 我想知道你花了幾個小時😀
大聲笑!! 問題是:如果我說完我想說的一切,我要花幾個小時? 無窮 !! 🙂
一件事我不知道,好文章!
謝謝。 很高興與您分享。
很好的解釋。 恭喜,真的有用!
很高興您發現它有用。 所以寫是一種榮幸。
這應該特別。 喜歡精選但有非常具體的用途。 非常有用,儘管我希望看到它適用於Vim。
這是一個問自己的問題。 我想到了更多關於正則表達式的文章。 我可以談談其中的vim。 它與我在本文中解釋的內容有所不同。 這是繼續下去的問題。 🙂
好!
你的文章非常好,很有趣,最近(現在)我在我的網站上發布了一個我準備了幾天的條目,其中我收集了正則表達式的元字符列表和一些示例。進入是公平的 DesdeLinux 並查看同一主題的條目!
如果有什麼安慰的話,我的貓就更多了
當然,正則表達式是最有用的東西之一,例如,我通常使用它們來修剪命令的輸出並保留我感興趣的部分,然後在bash腳本中與之交互。 我在大學裡也經常使用它們,它們對於編譯器的構造(在詞典詞典和解析器的定義中)至關重要。 簡而言之,整個世界。
問候和非常非常好的工作。
非常感謝。
我也喜歡你的文章。 它比我的要簡潔。 它可以作為快速參考。 我們同時寫了它們是一個巧合。 您可以看到人們對該主題感興趣。 🙂
傻瓜的正則表達式=),現在對我來說更清楚了,一種為grep輸出帶有顏色的方法是在.bashrc中創建一個別名grep ='grep –color = always',以防萬一。為某人工作。
問候
真正。 這是另一種方式。 感謝您的輸入。 🙂
O_O…一份貢獻! O_O ...
非常感謝您的帖子,我等待了一段時間,諸如此類的大聲笑,我將其打開以便在家中安靜地閱讀它,零麻煩地集中大聲笑。
謝謝你的文章,我真的很😀
我知道你會喜歡的大聲笑!! 事實是,很多事情都遺漏了,但我已經想到了第二部分。 🙂
很棒的文章,只要我昨天讀過,對我的學生來說,今天我上的課將會更加輕鬆!
大聲笑!! 太糟糕了,我遲到了,但很高興它很有用。 🙂
終於!!!,這個帖子超級好...我終於找到了可以清楚解釋正則表達式的內容.....
那裡有很多信息,但是要找到易於理解的東西卻更加困難。 我很高興填補了這一空白。 🙂
問候。
嘿,我需要幫助,我必須在/ var / log中使用以下格式進行搜索:yymmdd,日誌類似於130901.log -130901.log,我必須搜索1月11日至XNUMX月XNUMX日之間的所有日誌,我唯一要做的就是刪除了整個九月,但我不知道如何完成整個鏈條:
例如:1309 [0-3]會將1月30日至1月11日之間的日誌返回給我,但我不知道如何在XNUMX月XNUMX日至XNUMX日也進入同一鏈。
使用正則表達式來完成它有點複雜。 我想到這樣的事情可能會起作用:
13(09[0-3]|10(0|1[01]))
它是擴展的正則表達式。 您沒有說您正在使用哪個工具,所以我不能給您更多細節。
無論如何,我認為是這種情況,而不是使用正則表達式,最好使用find進行。 您可以嘗試如下操作:
找。 -newermt '01 Sep'-a! -newermt '11 oct'-打印
運氣。 希望這可以幫到你。
您好!首先,我想感謝您的工作,因為此頁面在我最好的Linux站點的“前3名”之內。
我正在練習,但不知道為什麼電話號碼上的RegExp對我不起作用,原因是我缺少“ -E”(這要歸功於這篇文章)。
我想問你,如果您不熟悉RegExp上的練習的不錯的pdf或網站,儘管稍加想像就可以自己練習發明它們。
問候,巴勃羅。
很好,我已經讀完了,是的,現在我需要阿司匹林
我見過的關於正則表達式的最好解釋。 感謝作者分享這項工作。
問候。
我真的很喜歡一個很好的解釋