Sed教程(四):基本命令、特殊字符、字符串

本教程将介绍一些有用的sed命令和使用示例。考虑一下我们有一个文本文件books.txt待处理,它有以下内容:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

删除 d 命令

sed删除命令用 d 字符表示,并将其用于删除从一个给定的模式缓冲器的一行或多行。以下是 sed 删除命令的基本语法:

[address1[,address2]]d

这里address1和address2分别为起始和结束地址,其可以是行号或模式串。这两个地址是可选参数,如果不提供它们作为前缀-d命令,那么它会删除,如下图所示所有行:

[jerry]$ sed 'd' books.txt 

上面的命令将删除所有传递给 sed 的行并且没有行数据会打印在屏幕上。

下面指示 sed 只在某些行上使用。下面的例子中只删除4行。

[jerry]$ sed '4d' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

此外,sed也接受用逗号分隔地址范围(,)。可以指示sed 删除N1到N2行。例如,下面的例子将删除从2到4的所有行。

[jerry]$ sed '2,4d' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

也可以指定模式作为地址。下面的示例删除作者是 Paulo Coelho的所有书籍。

[jerry]$ sed '/Paulo Coelho/d' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
6) A Game of Thrones, George R. R. Martin, 864 

也可以使用文本模式指定一个地址范围。下面的示例删除模式Storm 和Fellowship之间的所有行。

[jerry]$ sed '/Storm/,/Fellowship/d' books.txt  
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 
可以使用美元符号($),加号(+),和波浪符号(〜)运算符使用sed -d命令删除。

写入w 命令

sed的写命令是由 w 字符表示,并且它用于存储模式缓冲区的一个文件中内容。以下是sed 写命令的基本语法:

[address1[,address2]]w 

这里,address1 和 address2 分别是模式缓冲存储器的起始和结束地址,该地址可以是行号或模式串。这两个地址是可选参数,如果不提供它们的前缀给w命令,那么它将存储完整的模式缓冲区到给定的文件,如下所示:

[jerry]$ sed -n 'w books.bak' books.txt 

上面的命令将创建另一个名为books.bak的文件。这是books.txt文件复制文件。

sed允许创建包含源文件只有某些行的文件。以下命令是副本只从books.txt偶数行数据到books.bak文件。

[jerry]$ sed -n '2~2w books.bak' books.txt  

如果将检查books.bak文件的内容,那么它将有以下几行:

2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
6) A Game of Thrones, George R. R. Martin, 864 

也可以指定模式作为地址。下面的例子中存储作者为 Paulo Coelho 的所有书籍。

[jerry]$ sed -n -e '/Paulo Coelho/w books.bak' books.txt

如果将检查books.bak文件的内容,那么它将有以下几行:

3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288

追加 a 命令

任何一个文本编辑器的最有用的操作是提供附/追加功能。sed通过其由一个字符表示追加命令支持该操作。以下是sed追加命令的基本语法:

[address]a  'text to be appended'

这里的地址是模式缓冲区地址,可以是行号或模式字符串来表示,其中的文本将被追加的位置。以下是追加后的行数4新书项命令。

[jerry]$ sed '4a 7) Adultry, Paulo Coelho, 234' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
7) Adultry, Paulo Coelho, 234 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

可以使用$符号插入的文件结束后面的行,如下所示:

[jerry]$ sed '$a 7) Adultry, Paulo Coelho, 234' books.txt

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
7) Adultry, Paulo Coelho, 234

除了行数,还可以使用文本模式指定一个地址。例如,下面的例子匹配字符串后追加文本The Alchemist.

[jerry]$ sed '/The Alchemist/a 7) Adultry, Paulo Coelho, 234' books.txt  

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
7) Adultry, Paulo Coelho, 234 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 

修改 c 命令

sed提供更改或更换用c字符来表示命令。此命令可以帮助更换新文本的现有行。以下是 sed 改变命令的基本语法:

[address1[,address2]]c 'Next text'

这里,address1 和 address2 分别是模式缓冲区的起始和结束地址,该地址可以是行号或模式串。这两个地址是可选参数,如果不提供前缀,则该命令将替换为新文本的每一行,如下所示:

[jerry]$ sed 'c This is new text' books.txt 

执行上面的代码,会得到如下结果:

This is new text
This is new text
This is new text
This is new text
This is new text
This is new text

下面是示例替换一些其他文本的第三行。

[jerry]$ sed '3 c 3) Adultry, Paulo Coelho, 324' books.txt

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

还可以指定要匹配并采用c运算符的帮助下替换模式如下:

[jerry]$ sed '/The Alchemist/c 3) Adultry, Paulo Coelho, 324' books.txt

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 

sed 还允许替换多行以及一行。下面的示例是从第4行到第6行,将它们替换为新的文本。

[jerry]$ sed '4, 6c 4) Adultry, Paulo Coelho, 324' books.txt  

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) Adultry, Paulo Coelho, 324

插入 i 命令

插入命令工作起来作为追加的方式相同。唯一的区别在于,它插入一个特定位置之前的行。以下是sed的插入命令的基本语法:

[address]i 'Text to be inserted' 

这里地址是模式缓冲区地址,可以用行号或模式串来表示,其中的文本将被插入的位置。下面是插入第4行之前的一本新书项命令。

[jerry]$ sed '4 i 7) Adultry, Paulo Coelho, 324' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
7) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

在一个文件的开头插入文本,提供的行地址为1.下列命令说明这一点:

[jerry]$ sed '1 i 7) Adultry, Paulo Coelho, 324' books.txt

执行上面的代码,会得到如下结果:

7) Adultry, Paulo Coelho, 324
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

下面的命令插入的最后一行前行。

[jerry]$ sed '$ i 7) Adultry, Paulo Coelho, 324' books.txt

执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
7) Adultry, Paulo Coelho, 324
6) A Game of Thrones, George R. R. Martin, 864

转换 y 命令

sed提供一个命令转换到字符,它表示为y。它通过位置转换字符。以下是sed转换命令基本语法:

[address1[,address2]]y/list-1/list-2/

注意,转换是基于字符的,从列表1到可用的字符在表2中的位置是相同的位置和两个列表必须是明确的字符列表。正则表达式和字符集是不支持的。此外,表1和表2的尺寸必须相同。

下面的示例将大写字母为小写字母:

[jerry]$ echo "BCDAFE" | sed 'y/ABCDEF/abcdef/' 

执行上面的代码,会得到如下结果:

bcdafe

Sed l 命令

sed使用 -l 命令可以在文本显示隐藏字符。例如,\t制表符和$符结束行。下面给出的是sed的 i 命令的语法。

[address1[,address2]]l 

or

[address1[,address2]]l [len] 

现在,在 books.txt 输入一个标签空间,并尝试使用 l 命令显示的内容:

[jerry]$ sed -n 'l' books.txt

执行上面的代码,会得到如下结果:

1)\tA Storm of Swords, George R. R. Martin, 1216 $
2) The Two Towers, J. R. R. Tolkien, 352 $
3) The Alchemist, Paulo Coelho, 197 $
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 $
5) The Pilgrimage, Paulo Coelho, 288 $
6) A Game of Thrones, George R. R. Martin, 864$

类似于其他sed的命令,它也接受行号和模式作为地址。

可以指示sed的一定字符数之后进行换行。下面的例子25个字符后换行。

[jerry]$ sed -n 'l 25' books.txt

执行上面的代码,会得到如下结果:

1) A Storm of Swords,Geo\ 
rge R. R. Martin,1216$ 
2) The Two Towers,J. R. \ 
R. Tolkien,352$ 
3) The Alchemist,Paulo C\ 
oelho,197$ 
4) The Fellowship of the\ 
 Ring,J. R. R. Tolkien,4\ 
32$ 
5) The Pilgrimage,Paulo \ 
Coelho,288$ 
6) A Game of Thrones,Geo\ 
rge R. R. Martin ,864$

缠绕限0意味着永远断行,除非有一个新行字符。下面简单的命令说明了这一点。

[jerry]$ sed -n 'l 0' books.txt 

执行上面的代码,会得到如下结果:

1) A Storm of Swords,George R. R. Martin,1216$ 
2) The Two Towers,J. R. R. Tolkien,352$ 
3) The Alchemist,Paulo Coelho,197$ 
4) The Fellowship of the Ring,J. R. R. Tolkien,432$ 
5) The Pilgrimage,Paulo Coelho,288$ 
6) A Game of Thrones,George R. R. Martin,864$ 

退出 q 命令

退出命令表示 sed 退出当前执行流程,它是由q命令表示。以下是 sed 的基本语法退出命令:

[address]q 
[address]q [value]

需要注意的是退出命令不接受地址范围,它仅支持一个地址。默认情况下,Sed如下读取,执行和重复的工作流程;但退出命令时只是停止当前执行并退出来。

以下是命令从该文件的第3行打印。

[jerry]$ sed '3 q' books.txt

在执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

还可以使用文本模式,而不是行号。当一个给定的模式匹配成功如下命令退出。

[jerry]$ sed '/The Alchemist/ q' books.txt 

在执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

除了这一点,sed还可以接受,可用于作为退出状态值。以下命令显示了它的退出状态为100。

[jerry]$ sed '/The Alchemist/q 100' books.txt

在执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

现在让我们验证的退出状态。

[jerry]$ echo $? 

在执行上面的代码,会得到如下结果:

100

读取 r 命令

可以让Sed读取文件的内容,并显示在一个特定的条件相匹配。读指令由r操作者来表示。以下是Sed的基本语法读取命令:

[address]r file

让我们用一个简单的例子了解它。创建一个名为junk.txt示例文件。

[jerry]$ echo "This is junk text." > junk.txt 

下面的命令指示Sed来读取 junk.txt 的内容,在第三行之后插入。

[jerry]$ sed '3 r junk.txt' books.txt 

在执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
This is junk text. 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

下面的命令在第三,第四和第五行之后插入 junk.txt 内容。

[jerry]$ sed '3, 5r junk.txt' books.txt 

在执行上面的代码,得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
This is junk text. 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
This is junk text. 
5) The Pilgrimage, Paulo Coelho, 288 
This is junk text. 
6) A Game of Thrones, George R. R. Martin, 864

类似其他的sed命令,读取命令也接受模式作为地址。例如,下面的命令插入junk.txt 文件内容时,所述模式匹配成功。

[jerry]$ sed '/Paulo/ r junk.txt' books.txt  

在执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
This is junk text. 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
This is junk text. 
6) A Game of Thrones, George R. R. Martin, 864 

执行 e 命令

我们可以从Sed使用执行命令,执行外部命令,它是通过电子邮件操作符表示。以下是Sed执行命令的基本语法:

[address1[,address2]]e [command]

这里,address1 和 address2是模式缓冲存储器的地址,该地址可以为行号或模式字符串,及命令将执行一个给定的地址。

例如,下面的 sed 命令是当遇到从给定的文件中的第三行之前执行 UNIX 日期命令。

[jerry]$ sed '3 e date' books.txt

当执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
Sun Sep  7 18:04:49 IST 2014 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

类似其他的命令,它也可以接受模式作为地址。例如,下面示例执行date命令,当一个模式匹配成功。注意,每一个模式匹配后,首先执行该命令,然后将模式缓冲区的内容显示。

[jerry]$ sed '/Paulo/ e date' books.txt 

当执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
Sun Sep  7 18:06:04 IST 2014 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
Sun Sep  7 18:06:04 IST 2014 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

当 e 之后没有命令提供,它将该模式缓冲区的内容作为一个外部命令。为了说明这一点,创建一些简单的命令在 commands.txt 的文件中。

[jerry]$ echo -e "date\ncal\nuname" > commands.txt 
[jerry]$ cat commands.txt

当执行上面的代码,会得到如下结果:

date 
cal 
uname

从文件的命令不言自明。下面简单的例子,提供了一个使用 sed 脚本的命令:

[jerry]$ sed 'e' commands.txt 

当执行上面的代码,会得到如下结果:

Sun Sep  7 18:14:20 IST 2014 
   September 2014      
Su Mo Tu We Th Fr Sa   
    1  2  3  4  5  6   
 7  8  9 10 11 12 13   
14 15 16 17 18 19 20   
21 22 23 24 25 26 27   
28 29 30               
                       
Linux 

正如其他sed命令,在执行命令也接受地址的所有的有效范围。

杂项命令

默认情况下,sed操作在一行上,但是它也可以在多行上操作。多行命令由大写字母表示。例如,多行命令不同的是,N个命令不清除并打印模式空间。相反,它增加了一个新行(\n),在当前的模式空间的末端,并从输入文件中的下一行追加到当前模式空间,并与Sed的标准流量通过执行Sed命令的其余部分将继续。下面给出的是N命令的语法。

[address1[,address2]]N

稍微修改 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

让我们打印一个逗号分隔的书名和各自的作者名单。下面的例子说明了这一点。

[jerry]$ sed 'N; s/\n/,/g' 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

了解上面的例子如何工作。 n命令读取第一行,即Storm 模式缓冲区,并追加\n接着的下一行。模式空间现在包含Swords\nGeorge R. R. Martin。在接下来的步骤中,我们用逗号替换换行符。

就像 p 这样的命令,我们有一个 P 命令打印的第一部分(最多嵌入的换行符)由 N 命令创建的多行模式空间。下面给出的是 P 命令的语法,它类似于p命令。

[address1[,address2]]P 

在前面的例子中,我们看到了N命令创建的书名和作者的新一行 - 分隔的列表。打印它仅第一部分,即,这本书的标题。下面的命令说明了这一点。

[jerry]$ sed -n 'N;P' books.txt

当执行上面的代码,会得到如下结果:

A Storm of Swords 
The Two Towers 
The Alchemist 
The Fellowship of the Ring 
The Pilgrimage 
A Game of Thrones

请注意,在不存在 N,它的行为相同于 p 命令。下面简单的命令说明了这种情况。

[jerry]$ sed -n 'P' 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

除了这一点,Sed还提供了用于检查版本的一个 v 命令。如果所提供的版本大于所述安装 sed 的版本,然后命令执行失败。请注意,此选项是GNU具体,可能无法与Sed的其他版本的工作。下面给出的是 v 命令的语法。

[address1[,address2]]v [version]

首先,找出Sed的当前版本。

[jerry]$ sed --version 

当执行上面的代码,会得到如下结果:

sed (GNU sed) 4.2.2 

在下面的例子中,Sed版本高于4.2.2版本,因此sed命令中止执行。

[jerry]$ sed 'v 4.2.3' books.txt 

当执行上面的代码,会得到如下结果:

sed: -e expression #1, char 7: expected newer version of sed

但是,如果所提供的版本是小于或等于4.2.2版本,则命令会按预期工作。

[jerry]$ sed 'v 4.2.2' 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



Sed提供了被当作命令两个特殊字符。本章说明了这两个特殊字符的使用。尝试使用这些命令,考虑有一个文本文件books.txt待处理,它有以下内容:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

= 命令

=命令将行号后跟其标准输出流的内容。下面给出的是=命令的语法:

[address1[,address2]]=

这里address1 和 address2分别为起始和结束地址,其可以是行号或模式串。这两个地址是可选参数,如果不提供它们作为前缀=命令,如下图所示,将打印的所有行的行号:

[jerry]$ sed '=' books.txt 

当执行上面的代码,会得到如下结果:

1 
1) A Storm of Swords, George R. R. Martin, 1216 
2 
2) The Two Towers, J. R. R. Tolkien, 352 
3 
3) The Alchemist, Paulo Coelho, 197 
4 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5 
5) The Pilgrimage, Paulo Coelho, 288 
6 
6) A Game of Thrones, George R. R. Martin, 864

下面的命令打印首4行的行号和剩余不带行号:

[jerry]$ sed '1,4=' books.txt 

当执行上面的代码,会得到如下结果:

1
1) A Storm of Swords, George R. R. Martin, 1216
2
2) The Two Towers, J. R. R. Tolkien, 352
3
3) The Alchemist, Paulo Coelho, 197
4
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

下面的例子打印包含模式“Paulo”的行号。

[jerry]$ sed '/Paulo/=' books.txt 

当执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

下面的例子将打印仅在最后一行的行号:

[jerry]$ sed '$=' books.txt

当执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6
6) A Game of Thrones, George R. R. Martin, 864

下面的例子仅打印对所有行的行号:

[jerry]$ sed -n '='  books.txt

当执行上面的代码,会得到如下结果:

1
2
3
4
5
6

下面的例子打印文件中的行的总数:

[jerry]$ sed -n '$='  books.txt

当执行上面的代码,会得到如下结果:

6

& 命令

Sed 支持特殊字符和存储匹配的模式,每当一个模式匹配成功。它经常被用于替代命令。看看如何能够利用这种高效的特点。

在book.txt文件中的每一行编号。添加词语数量在每一行的开头。下面的例子说明了这一点:

[jerry]$ sed 's/[[:digit:]]/Book number &/' books.txt

当执行上面的代码,会得到如下结果:

Book number 1) A Storm of Swords, George R. R. Martin, 1216 
Book number 2) The Two Towers, J. R. R. Tolkien, 352 
Book number 3) The Alchemist, Paulo Coelho, 197 
Book number 4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
Book number 5) The Pilgrimage, Paulo Coelho, 288 
Book number 6) A Game of Thrones, George R. R. Martin, 864 

这个例子是很简单的。首先寻找一个数字,这是行号的第一次出现(这就是为什么使用[[:数字:]])和桑达自动存储在特殊字符和匹配模式。在第二步骤中,我们将插入每个匹配的模式,也就是说,每行之前之前词语的数量。

再举一个例子。在book.txt文件,最后一个数字是书的页数。在这之前加上“Pages=”。要做到这一点,找到数字的最后一次出现,并用“Pages=&”代替。这里,&存储匹配模式,即,页面的数量

[jerry]$ sed 's/[[:digit:]]*$/Pages = &/' books.txt 

当执行上面的代码,会得到如下结果:

1) A Storm of Swords, George R. R. Martin, Pages = 1216 
2) The Two Towers, J. R. R. Tolkien, Pages = 352 
3) The Alchemist, Paulo Coelho, Pages = 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, Pages = 432 
5) The Pilgrimage, Paulo Coelho,Pages = 288 
6) A Game of Thrones, George R. R. Martin, Pages = 864 

从目前来看,只记得[[:数字:]]* $找到数字的最后出现。在该章中的“正则表达式中,我们将探讨更多的正则表达式。



本教程将介绍一些字符串处理的重要sed命令。考虑我们有一个文本文件books.txt 要处理,它有以下内容:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

替换命令

“查找和替换”文本替换操作字符串最常见。下面给出的是替换命令的语法:

[address1[,address2]]s/pattern/replacement/[flags]

这里,address1 和 address2分别是起始和结束地址,它可以是行号或模式串。这两个地址是可选参数。

该模式是要替换的替换字符串的字符串。此外,也可以指定可选的标志,以增强功能。

以下是 sed 命令替换所有books.txt 用逗号与竖线(|)。

[jerry]$ sed 's/,/ | /' books.txt

执行上面的代码,得到如下结果:

1) A Storm of Swords |  George R. R. Martin, 1216
2) The Two Towers |  J. R. R. Tolkien, 352
3) The Alchemist |  Paulo Coelho, 197
4) The Fellowship of the Ring |  J. R. R. Tolkien, 432
5) The Pilgrimage |  Paulo Coelho, 288
6) A Game of Thrones |  George R. R. Martin, 864

如果仔细观察,只有第一个逗号替换,第二保持原样。为什么呢?只要模式匹配,Sed 替换为替换字符串并且移动到下一行。默认情况下,它仅替换第一次出现。要替换所有出现的,使用Sed全局标志(g)如下:

[jerry]$ sed 's/,/ | /g' books.txt

执行上面的代码,得到如下结果:

1) A Storm of Swords |  George R. R. Martin |  1216
2) The Two Towers |  J. R. R. Tolkien |  352
3) The Alchemist |  Paulo Coelho |  197
4) The Fellowship of the Ring |  J. R. R. Tolkien |  432
5) The Pilgrimage |  Paulo Coelho |  288
6) A Game of Thrones |  George R. R. Martin |  864

可以指示Sed执行文本替换,只有当一个模式匹配成功。下面的示例替换逗号(,)用竖线(|)仅当行包含模式。

[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt 

执行上面的代码,得到如下结果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage | Paulo Coelho | 288 
6) A Game of Thrones, George R. R. Martin, 864

Sed 也可以取代的模式发生的特定事件。替换逗号(,)以竖线的唯一的第二个实例(|)。下面是在sed命令(或标志的地方),当前匹配的第二个出现的有多少。

[jerry]$ sed 's/,/ | /2' books.txt

执行上面的代码,得到如下结果:

1) A Storm of Swords, George R. R. Martin | 1216 
2) The Two Towers, J. R. R. Tolkien | 352 
3) The Alchemist, Paulo Coelho | 197 
4) The Fellowship of the Ring, J. R. R. Tolkien | 432 
5) The Pilgrimage,Paulo Coelho | 288 
6) A Game of Thrones, George R. R. Martin  | 864

可以使用P标志,如下打印不仅改变的行:

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt

执行上面的代码,得到如下结果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288 

可以在另一个文件中保存更改的行。为了实现这种结果,可以使用 w 标志如下所示:

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt

现在 junk.txt 文件已全部更改的文件。让我们验证 junk.txt 文件的内容。

[jerry]$ cat junk.txt

执行上面的代码,得到如下结果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

执行不区分大小写的替换,可以使用i标志,这意味着忽略大小写。下面的例子执行不区分大小写的替换。

[jerry]$ sed  -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt

执行上面的代码,得到如下结果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

非标分隔符

通常,反斜杠(/)作为分隔符,但有时是用其它支持定界符以用 sed 更方便。

到目前为止,我们已经使用了只有反斜杠(/)字符作为分隔符,但我们也可以使用竖线(|),at符号(@),插入符号(^),感叹号作为分隔符(!)。下面的示例演示了如何使用其他字符作为分隔符。

下面的例子使用竖线(|)作为分隔符:

[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'

执行上面的代码,得到如下结果:

/home/jerry/src/sed/sed-4.2.2/sed

同样,我们可以用“at”符号(@)使用作为分隔符,如下所示:

[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'

执行上面的代码,得到如下结果:

/home/jerry/src/sed/sed-4.2.2/sed 

同样,我们可以使用插入符号(^)作为分隔符,如下所示:

[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'

执行上面的代码,得到如下结果:

/home/jerry/src/sed/sed-4.2.2/sed 

同样,我们可以使用感叹号作为分隔符如下(!):

[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'

执行上面的代码,得到如下结果:

/home/jerry/src/sed/sed-4.2.2/sed 

创建一个子串

我们学到了强大的替换命令。看看是否可以找到一个匹配的文本字符串。了解如何用一个例子来说明。

看看下面的文字:

[jerry]$ echo "Three One Two"

假设我们要安排成一个序列。意味着,它应该打印一份,再两个,最后三个。下面的单行代码执行。

[jerry]$ echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'

sed 子串可以通过使用分组操作员指定,并且它必须以转义字符作为前缀,即\(和\)。

在这里,\ w是一个正则表达式匹配任何字母或下划线和“+”号来匹配多个字符。换句话说,正则表达式 \(\w\+\)从输入串中的单个字相匹配。

这个子串由\N,N是子串号转介。因此,\2打印第二子串,即一个; \3打印第三子串,即两种;和\1打印第一子,即Three

让我们分开这些话通过逗号(,)并相应修改则表达式。

[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'

执行上面的代码,得到如下结果:

One,Two,Three

字符串替换标志

GNU Sed 提供可在替换字符串中使用一些特殊的转义序列。请注意,这些字符串替换标志是GNU具体指定,可能无法与Sed其他变种进行工作。在这里,我们将讨论的字符串替换标志。

 \L 标识

当在替换字符串中指定\L,它把该单词的所有剩余的字符,\L以小写字符。例如,字符“ULO”被视为小写字符。

[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt

执行上面的代码,得到如下结果:

3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288

\u 标识

\u被替换字符串指定,它把后\u,如大写字符前的字符。在下面的例子中,\u字符为'a'和'o'之前使用。因此,Sed将这些字符转为大写字母。

[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt

执行上面的代码,得到如下结果:

3) The Alchemist, pAulO Coelho, 197 
5) The Pilgrimage, pAulO Coelho, 288

\U 标识

当\U在替换字符串中指定,把单词的所有剩余的字符\U后为大写字母。

[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt 

执行上面的代码,得到如下结果:

3) The Alchemist, PAULO Coelho, 197 
5) The Pilgrimage, PAULO Coelho, 288

 \E 标识

\E标志应使用\L或\U。它标志\L或\U开始停止转换。在下面的例子中,只有第一个字被替换为大写字母。

[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt

执行上面的代码,得到如下结果:

3) The Alchemist, PAULO coelho, 197 
5) The Pilgrimage, PAULO coelho, 288


from: http://www.yiibai.com/sed/sed_useful_recipes.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值