位置:首页 > 高级语言 > Sed在线教程 > Sed正则表达式

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