Sed正則表達式

sed是強大,高效的處理正則表達式。一些複雜的任務,可以解決簡單的正則表達式。任何命令行專家都知道正則表達式的威力。

本教程介紹了標準的正則表達式,POSIX類的正則表達式和元字符。考慮我們有一個文本文件 books.txt 將被處理,它有以下內容:

A Storm of Swords, George R. R. Martin
The Two Towers, J. R. R. Tolkien
The Alchemist, Paulo Coelho
The Fellowship of the Ring, J. R. R. Tolkien
The Pilgrimage, Paulo Coelho
A Game of Thrones, George R. R. Martin

標準的正則表達式

行開始 (^)

插入符號(^)符號用於一行的開始匹配。下面的例子打印所有的啓動與模式「the」行。

[jerry]$ sed -n '/^The/ p' books.txt

執行上面的代碼,會得到如下結果:

The Two Towers, J. R. R. Tolkien
The Alchemist, Paulo Coelho
The Fellowship of the Ring, J. R. R. Tolkien
The Pilgrimage, Paulo Coelho

行尾 ($)

行尾是由美元符號($)符號表示。下面的例子打印「Coelho」結尾的行。

[jerry]$ sed -n '/Coelho$/ p' books.txt

執行上面的代碼,會得到如下結果:

The Alchemist, Paulo Coelho
The Pilgrimage, Paulo Coelho

單個字符(.)

點(.)匹配除行字符結尾的任何單個字符。下面的例子打印所有三個字母的單詞字符 「t」 結尾。

[jerry]$ echo -e "cat\nbat\nrat\nmat\nbatting\nrats\nmats" | sed -n '/^..t$/p'

執行上面的代碼,會得到如下結果:

cat
bat
rat
mat

匹配字符集合 ([])

字符集是用方括號([])表示。它用來匹配只有1個之中的幾個字符。下面的例子匹配模式「Call」和「Tall」,而不是「Ball」。

[jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[CT]all/ p'

執行上面的代碼,會得到如下結果:

Call
Tall

獨有集 ([^])

當使用的字符集使用時,插入符否定集在方括號字符。只有下面的示例打印「Ball」。

[jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[^CT]all/ p'

執行上面的代碼,會得到如下結果:

Ball

字符範圍 ([-])

當被提供的字符範圍,則正則表達式匹配在方括號中指定的範圍內的任何字符。下面的例子匹配「Call」和「Tall」,而不是「Ball」。

[jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[C-Z]all/ p'

執行上面的代碼,會得到如下結果:

Call
Tall

現在,讓我們修改範圍爲「A-P」,並觀察結果。

[jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[A-P]all/ p'

執行上面的代碼,會得到如下結果:

Call
Ball

零到一次出現 (\?)

問號(\?)匹配零個或一個匹配前面的字符。下面的例子匹配「Behaviour」和「Behavior」。在這裏,我們通過使用「\?」使「u」作爲一個可選的字符。

[jerry]$ echo -e "Behaviour\nBehavior" | sed -n '/Behaviou\?r/ p'

執行上面的代碼,會得到如下結果:

Behaviour
Behavior

一次或多次出現 (\+)

加號(\+)匹配前面的字符出現一次或多次。下面的例子匹配「2」出現一次或多次。

[jerry]$ echo -e "111\n22\n123\n234\n456\n222" | sed -n '/2\+/ p'

執行上面的代碼,會得到如下結果:

22
123
234
222

零或多次出現 (*)

星號(*)匹配零個或多個發生了前面的字符。下面的例子匹配"ca", "cat", "catt"等依此類推。

[jerry]$ echo -e "ca\ncat" | sed -n '/cat*/ p'

執行上面的代碼,會得到如下結果:

ca
cat

n個重複 {n}

{n}表達完全一致的「n」出現前面的字符。下面的例子打印只有三個數字。但在這之前,你需要創建以下文件,該文件僅包含數字。考慮 numbers.txt 有以下內容:

1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000

現在讓我們編寫 Sed 表達式。在這裏,對花括號中的「\」字符轉義。

[jerry]$ sed -n '/^[0-9]\{3\}$/ p' numbers.txt

執行上面的代碼,會得到如下結果:

100

最少出現n個 {n,}

{n,} 表達式匹配,至少是「n」出現前面的字符。下面的例子打印大於或等於5個數字的所有數字。

[jerry]$ sed -n '/^[0-9]\{5,\}$/ p' numbers.txt

執行上面的代碼,會得到如下結果:

10000
100000
1000000
10000000
100000000
1000000000

M到N次出現 {m, n}

{m, n} 表達式匹配,至少是「M」和最「N」出現前面的字符。下面的例子打印所有具有至少5個數字,但不超過8位的數字。

[jerry]$ sed -n '/^[0-9]\{5,8\}$/ p' numbers.txt

執行上面的代碼,會得到如下結果:

10000
100000
1000000
10000000

管道(|)

管道符的行爲類似於邏輯或運算。它從管的兩側相匹配的條目。下面的例子要麼匹配"str1" 和 "str3"。這裏,一對括號和管道 (|) 由「\」字符轉義。

[jerry]$ echo -e "str1\nstr2\nstr3\nstr4" | sed -n '/str\(1\|3\)/ p'

執行上面的代碼,會得到如下結果:

str1
str3

字符轉義

有哪些有在Sed有特殊含義的特殊字符。例如,用「\n」表示換行,回車被爲「\r」表示,依此類推。要使用這些字符轉換成普通的ASCII,我們必須使用反斜槓(\)字符轉義。本章說明了轉義特殊字符。

轉義 "\"

下面的例子匹配的模式「\」。

[jerry]$ echo 'str1\str2' | sed -n '/\\/ p'

執行上面的代碼,會得到如下結果:

str1\str2

轉義 "\n"

下面的示例將新行字符匹配。

[jerry]$ echo 'str1\nstr2' | sed -n '/\\n/ p'

執行上面的代碼,會得到如下結果:

str1\nstr2

轉義 "\r"

下面的例子回車匹配。

[jerry]$ echo 'str1\rstr2' | sed -n '/\\r/ p'

執行上面的代碼,會得到如下結果:

str1\rstr2 

轉義"\dnnn"

這個匹配一個字符的十進制ASCII碼值是「nnn」。下面的例子中只匹配字符「a」。

[jerry]$ echo -e "a\nb\nc" | sed -n '/\d97/ p'

執行上面的代碼,會得到如下結果:

a

轉義 "\onnn"

這個匹配字符的八進制ASCII碼值是「nnn」。下面的例子僅匹配字符「b」。

[jerry]$ echo -e "a\nb\nc" | sed -n '/\o142/ p'

執行上面的代碼,會得到如下結果:

b

這個匹配字符的十六進制ASCII碼值是「nnn」。下面的例子中只匹配字符「c」。

[jerry]$ echo -e "a\nb\nc" | sed -n '/\x63/ p'

執行上面的代碼,會得到如下結果:

c

正則表達式POSIX類

有哪些有Sed 特殊的含義一定的保留字。這些保留字被稱爲POSIX類正則表達式。本節介紹Sed支持POSIX類。

[:alnum:]

這意味着按字母和數字字符。下面的例子只匹配「One」和「123」,但不匹配製表符。

[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alnum:]]/ p'

執行上面的代碼,會得到如下結果:

One
123

[:alpha:]

這意味着只有字母字符。下面的例子只匹配單詞「One」。

[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alpha:]]/ p'

執行上面的代碼,會得到如下結果:

One

[:blank:]

這意味着空白字符可以是任何空格或製表符。下面的例子只匹配製表符。

[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:space:]]/ p' | cat -vte

執行上面的代碼,會得到如下結果:

^I$

注意,該命令「cat -vte」用於顯示製表符(^ I)中。

[:digit:]

這意味着只有小數。下面的例子只匹配數字「123」。

[jerry]$ echo -e "abc\n123\n\t" | sed -n '/[[:digit:]]/ p'

執行上面的代碼,會得到如下結果:

123

[:lower:]

這意味着只有小寫字母。下面的例子只匹配「one」。

[jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:lower:]]/ p'

執行上面的代碼,會得到如下結果:

one

[:upper:]

這意味着只有大寫字母。下面的例子只匹配 "TWO".

[jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:upper:]]/ p'

執行上面的代碼,會得到如下結果:

TWO

[:punct:]

它意味着標點符號包括非空格或字母數字字符

[jerry]$ echo -e "One,Two\nThree\nFour" | sed -n '/[[:punct:]]/ p'

執行上面的代碼,會得到如下結果:

One,Two

[:space:]

這意味着空格字符。下面的例子說明了這一點。

[jerry]$ echo -e "One\n123\f\t" | sed -n '/[[:space:]]/ p' | cat -vte

執行上面的代碼,會得到如下結果:

123^L^I$

元字符

像傳統的正則表達式,Sed也支持特殊字符。這些是Perl風格正則表達式。需要注意的是元字符的支持是GNU Sed,可能無法與Sed的其他變種的工作。讓我們詳細討論的元字符。

單詞邊界 (\b)

「\b」元字符的字邊界匹配。例如,「\bthe\b」匹配「the」而不是"these", "there", "they", "then", 依此類推。下面的例子說明了這一點。

[jerry]$ echo -e "these\nthe\nthey\nthen" | sed -n '/\bthe\b/ p'

執行上面的代碼,會得到如下結果:

the

非單詞邊界(\B)

「\B」元字符匹配非單詞邊界。例如,「the\B」匹配「,這些」these「和「they」而不是「the」。下面的例子說明了這一點。

[jerry]$ echo -e "these\nthe\nthey" | sed -n '/the\B/ p'

執行上面的代碼,會得到如下結果:

these
they

單空白 (\s)

「\s」元字符意味着單個空格字符。下面的例子匹配「Line\t1」,但不匹配「Line1」。

[jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\s/ p'

執行上面的代碼,會得到如下結果:

Line 1

單非空白 (\S)

「\S」元字符意味着單個空格字符。下面的例子匹配「Line2」,但不匹配「Line\t1」。

[jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\S/ p'

執行上面的代碼,會得到如下結果:

Line2

單字字符 (\w)

「\W」元字符意味着單個單詞字符,即字母字符,數字和下劃線(_)。下面的例子說明了這一點。

[jerry]$ echo -e "One\n123\n1_2\n&;#" | sed -n '/\w/ p'

執行上面的代碼,會得到如下結果:

One
123
1_2

單非單詞字符 (\W)

「\W」元字符意味着一個非單詞字符,以「\w」正好相反。下面的例子說明了這一點。

[jerry]$ echo -e "One\n123\n1_2\n&;#" | sed -n '/\W/ p'

On executing the above code, you get the following result:

&;#

模式空間的開始 (\`)

「\」'元字符意味着將模式空間的開始位置。下面的例子只匹配單詞「One」。

[jerry]$ echo -e "One\nTwo One" | sed -n '/\`One/ p'

執行上面的代碼,會得到如下結果:

One