當我們在 unix/linux 下使用特定的指令從字元串或檔案中讀取或編輯文本時,我們經常需要過濾輸出以得到感興趣的部分。這時正規表達式就派上用場了。
<a target="_blank"></a>
正規表達式可以定義為代表若幹個字元序列的字元串。它最重要的功能之一就是它允許你過濾一條指令或一個檔案的輸出、編輯文本或配置檔案的一部分等等。
正規表達式由以下内容組合而成:
普通字元,例如空格、下劃線、a-z、a-z、0-9。
可以擴充為普通字元的元字元,它們包括:
<code>(.)</code> 它比對除了換行符外的任何單個字元。
<code>(*)</code> 它比對零個或多個在其之前緊挨着的字元。
<code>[ character(s) ]</code> 它比對任何由其中的字元/字元集指定的字元,你可以使用連字元(-)代表字元區間,例如 [a-f]、[1-5]等。
<code>^</code> 它比對檔案中一行的開頭。
<code>$</code> 它比對檔案中一行的結尾。
<code>\</code> 這是一個轉義字元。
你必須使用類似 awk 這樣的文本過濾工具來過濾文本。你還可以把 awk 自身當作一個程式設計語言。但由于這個指南的适用範圍是關于使用 awk 的,我會按照一個簡單的指令行過濾工具來介紹它。
awk 的一般文法如下:
<code># awk 'script' filename</code>
此處 <code>'script'</code> 是一個由 awk 可以了解并應用于 filename 的指令集合。
它通過讀取檔案中的給定行,複制該行的内容并在該行上執行腳本的方式工作。這個過程會在該檔案中的所有行上重複。
該腳本 <code>'script'</code> 中内容的格式是 <code>'/pattern/ action'</code>,其中 <code>pattern</code> 是一個正規表達式,而<code>action</code> 是當 awk 在該行中找到此模式時應當執行的動作。
在下面的例子中,我們将聚焦于之前讨論過的元字元。
下面的例子列印檔案 /etc/hosts 中的所有行,因為沒有指定任何的模式。
<code># awk '//{print}' /etc/hosts</code>
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuEjYlNWZ3oXazEzYlFWNyN3M1cTMzIzLcdTMvw1NwYTMwIzLc1WdixWYvwFduVWboNWY0RXYvwVY0FGZvwVZt5CevJWcu42Y4VnbpxWLuR2Lc9CX6MHc0RHaiojIsJye.gif)
awk 列印檔案中的所有行
在下面的示例中,指定了模式 <code>localhost</code>,是以 awk 将比對檔案 <code>/etc/hosts</code> 中有 <code>localhost</code> 的那些行。
<code># awk '/localhost/{print}' /etc/hosts</code>
awk 列印檔案中比對模式的行
在下面的例子中,符号 <code>(.)</code> 将比對包含 loc、localhost、localnet 的字元串。
這裡的正規表達式的意思是比對 l一個字元c。
<code># awk '/l.c/{print}' /etc/hosts</code>
使用 awk 列印檔案中比對模式的字元串
(lctt 譯者注:此處原文作者了解有誤,感謝微信讀者“止此而已”的提醒,<code>*</code> 在此處表示其前一個字元重複零次或多次,是以實際上相當于 <code>*</code> 及前面的字元是無用的。)
在下面的例子中,将比對包含 localhost、localnet、lines, capable 的字元串。将比對帶有 <code>c</code> 字元的字元串。
<code># awk '/l*c/{print}' /etc/localhost</code>
使用 awk 比對檔案中的字元串
你可能也意識到 <code>(*)</code> 将會嘗試比對它可能檢測到的最長的比對。
讓我們看一看可以證明這一點的例子,正規表達式 <code>t*t</code> 的意思是在下面的行中比對以 <code>t</code> 開始和 <code>t</code> 結束的字元串:将比對帶有 t 字元的字元串:
<code>this is tecmint, where you get the best good tutorials, how to's, guides, tecmint.</code>
當你使用模式 <code>/t*t/</code> 時,會得到如下可能的結果:以下字元串隻是有 t 字元而已:
<code>this is t</code>
<code>this is tecmint</code>
<code>this is tecmint, where you get t</code>
<code>this is tecmint, where you get the best good t</code>
<code>this is tecmint, where you get the best good tutorials, how t</code>
<code>this is tecmint, where you get the best good tutorials, how tos, guides, t</code>
<code>this is tecmint, where you get the best good tutorials, how tos, guides, tecmint</code>
在 <code>/t*t/</code> 中的通配符 <code>(*)</code> 将使得 awk 選擇比對的最後一項:以下字元串隻是有 t 字元而已:
<code>this is tecmint, where you get the best good tutorials, how to's, guides, tecmint</code>
以集合 [al1] 為例,awk 将比對檔案 /etc/hosts 中所有包含字元 a 或 l 或 1 的字元串。
<code># awk '/[al1]/{print}' /etc/hosts</code>
使用 awk 列印檔案中比對的字元
下一個例子比對以 <code>k</code> 或 <code>k</code> 開始(非指行首是該字母),後面跟着一個 <code>t</code> 的字元串:
<code># awk '/[kk]t/{print}' /etc/hosts</code>
awk 所能了解的字元:
<code>[0-9]</code> 代表一個單獨的數字
<code>[a-z]</code> 代表一個單獨的小寫字母
<code>[a-z]</code> 代表一個單獨的大寫字母
<code>[a-za-z]</code> 代表一個單獨的字母
<code>[a-za-z 0-9]</code> 代表一個單獨的字母或數字
讓我們看看下面的例子:
<code># awk '/[0-9]/{print}' /etc/hosts</code>
使用 awk 列印檔案中比對的數字
在上面的例子中,檔案 /etc/hosts 中的所有行都至少包含一個單獨的數字 [0-9]。
在下面的例子中,它比對所有以給定模式開頭的行:
<code># awk '/^fe/{print}' /etc/hosts</code>
<code># awk '/^ff/{print}' /etc/hosts</code>
使用 awk 列印與模式比對的行
它将比對所有以給定模式結尾的行:
<code># awk '/ab$/{print}' /etc/hosts</code>
<code># awk '/ost$/{print}' /etc/hosts</code>
<code># awk '/rs$/{print}' /etc/hosts</code>
使用 awk 列印與模式比對的字元串
它允許你将該轉義字元後面的字元作為文字,即了解為其字面的意思。
在下面的例子中,第一個指令列印出檔案中的所有行,第二個指令中我想比對具有 $25.00 的一行,但我并未使用轉義字元,因而沒有列印出任何内容。
第三個指令是正确的,因為一個這裡使用了一個轉義字元以轉義 $,以将其識别為 '$'(而非元字元)。
<code># awk '//{print}' deals.txt</code>
<code># awk '/$25.00/{print}' deals.txt</code>
<code># awk '/\$25.00/{print}' deals.txt</code>
結合轉義字元使用 awk
以上内容并不是 awk 指令用做過濾工具的全部,上述的示例均是 awk 的基礎操作。
原文釋出時間為:2016-07-18
本文來自雲栖社群合作夥伴“linux中國”