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”出现前面的字符。下面的例子打印只有三个数字。但在这之前,你需要创建以下文件,该文件仅包含数字。考虑 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”出现前面的字符。下面的例子打印大于或等于5个数字的所有数字。
[jerry]$ sed -n '/^[0-9]\{5,\}$/ p' numbers.txt
执行上面的代码,会得到如下结果:
10000 100000 1000000 10000000 100000000 1000000000
{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
下面的示例将新行字符匹配。
[jerry]$ echo 'str1\nstr2' | sed -n '/\\n/ p'
执行上面的代码,会得到如下结果:
str1\nstr2
下面的例子回车匹配。
[jerry]$ echo 'str1\rstr2' | sed -n '/\\r/ p'执行上面的代码,会得到如下结果:
str1\rstr2
这个匹配一个字符的十进制ASCII码值是“nnn”。下面的例子中只匹配字符“a”。
[jerry]$ echo -e "a\nb\nc" | sed -n '/\d97/ p'执行上面的代码,会得到如下结果:
a
这个匹配字符的八进制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
有哪些有Sed 特殊的含义一定的保留字。这些保留字被称为POSIX类正则表达式。本节介绍Sed支持POSIX类。
这意味着按字母和数字字符。下面的例子只匹配“One”和“123”,但不匹配制表符。
[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alnum:]]/ p'执行上面的代码,会得到如下结果:
One 123
这意味着只有字母字符。下面的例子只匹配单词“One”。
[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alpha:]]/ p'
执行上面的代码,会得到如下结果:
One
这意味着空白字符可以是任何空格或制表符。下面的例子只匹配制表符。
[jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:space:]]/ p' | cat -vte执行上面的代码,会得到如下结果:
^I$
注意,该命令“cat -vte”用于显示制表符(^ I)中。
这意味着只有小数。下面的例子只匹配数字“123”。
[jerry]$ echo -e "abc\n123\n\t" | sed -n '/[[:digit:]]/ p'执行上面的代码,会得到如下结果:
123
这意味着只有小写字母。下面的例子只匹配“one”。
[jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:lower:]]/ p'
执行上面的代码,会得到如下结果:
one
这意味着只有大写字母。下面的例子只匹配 "TWO".
[jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:upper:]]/ p'执行上面的代码,会得到如下结果:
TWO
它意味着标点符号包括非空格或字母数字字符
[jerry]$ echo -e "One,Two\nThree\nFour" | sed -n '/[[:punct:]]/ p'执行上面的代码,会得到如下结果:
One,Two
这意味着空格字符。下面的例子说明了这一点。
[jerry]$ echo -e "One\n123\f\t" | sed -n '/[[:space:]]/ p' | cat -vte执行上面的代码,会得到如下结果:
123^L^I$
像传统的正则表达式,Sed也支持特殊字符。这些是Perl风格正则表达式。需要注意的是元字符的支持是GNU Sed,可能无法与Sed的其他变种的工作。让我们详细讨论的元字符。
“\b”元字符的字边界匹配。例如,“\bthe\b”匹配“the”而不是"these", "there", "they", "then", 依此类推。下面的例子说明了这一点。
[jerry]$ echo -e "these\nthe\nthey\nthen" | sed -n '/\bthe\b/ p'执行上面的代码,会得到如下结果:
the
“\B”元字符匹配非单词边界。例如,“the\B”匹配“,这些”these“和“they”而不是“the”。下面的例子说明了这一点。
[jerry]$ echo -e "these\nthe\nthey" | sed -n '/the\B/ p'
执行上面的代码,会得到如下结果:
these they
“\s”元字符意味着单个空格字符。下面的例子匹配“Line\t1”,但不匹配“Line1”。
[jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\s/ p'执行上面的代码,会得到如下结果:
Line 1
“\S”元字符意味着单个空格字符。下面的例子匹配“Line2”,但不匹配“Line\t1”。
[jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\S/ p'
执行上面的代码,会得到如下结果:
Line2
“\W”元字符意味着单个单词字符,即字母字符,数字和下划线(_)。下面的例子说明了这一点。
[jerry]$ echo -e "One\n123\n1_2\n&;#" | sed -n '/\w/ p'执行上面的代码,会得到如下结果:
One 123 1_2
“\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