流编辑器 - 正则表达式



正是正则表达式使得 SED 强大而高效。许多复杂的任务都可以用正则表达式来解决。任何命令行专家都知道正则表达式的威力。

与许多其他 GNU/Linux 实用程序一样,SED 也支持正则表达式,通常称为regex。本章详细介绍了正则表达式。本章分为三个部分:标准正则表达式、POSIX 正则表达式类和元字符。

标准正则表达式

行首 (^)

在正则表达式术语中,插入符号 (^) 匹配行的开头。以下示例打印所有以模式“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

匹配字符集 ([])

在正则表达式术语中,字符集由方括号 ([]) 表示。它用于匹配多个字符中的一个。以下示例匹配模式“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

零次或一次出现 (\?)

在 SED 中,问号 (?) 匹配前面字符的零次或一次出现。以下示例匹配“Behaviour”以及“Behavior”。在这里,我们使用“\?”将“u”作为可选字符。

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

执行上述代码后,您将获得以下结果

Behaviour 
Behavior

一次或多次出现 (\+)

在 SED 中,加号 (+) 匹配前面字符的一次或多次出现。以下示例匹配“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”次出现。以下示例仅打印三位数。但在此之前,您需要创建以下仅包含数字的文件。

[jerry]$ cat 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”次出现。以下示例打印所有大于或等于五位数的数字。

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

执行上述代码后,您将获得以下结果

10000 
100000 
1000000
10000000 
100000000 
1000000000 

M 到 N 次出现 {m, n}

{m, n} 匹配前面字符的至少“m”次,最多“n”次出现。以下示例打印所有至少有五位数但不多于八位数的数字。

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

执行上述代码后,您将获得以下结果

10000 
100000 
1000000 
10000000 

管道 (|)

在 SED 中,管道字符的行为类似于逻辑 OR 操作。它匹配管道两侧的项目。以下示例匹配“str1”或“str3”。

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

执行上述代码后,您将获得以下结果

str1 
str3

请注意,括号对和管道 (|) 由“\”字符转义。

转义字符

某些字符是特殊字符。例如,换行符由“\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 正则表达式类

某些保留字具有特殊含义。这些保留字称为 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)

在 SED 中,“\s”表示单个空格字符。以下示例匹配“Line\t1”,但不匹配“Line1”。

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

执行上述代码后,您将获得以下结果

Line 1 

单个非空格 (\S)

在 SED 中,“\S”表示单个空格字符。以下示例匹配“Line2”,但不匹配“Line\t1”。

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

执行上述代码后,您将获得以下结果

Line2

单个单词字符 (\w)

在 SED 中,“\w”表示单个单词字符,即字母字符、数字和下划线 (_) 。以下示例说明了这一点。

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

执行上述代码后,您将获得以下结果

One 
123 
1_2

单个非单词字符 (\W)

在 SED 中,“\W”表示单个非单词字符,这与“\w”正好相反。以下示例说明了这一点。

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

执行上述代码后,您将获得以下结果

&;#

模式空间的开头 (\`)

在 SED 中,“\`”表示模式空间的开头。以下示例仅匹配单词“One”。

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

执行上述代码后,您将获得以下结果

One
广告