sed & awk之sed

sed处理文本的方法

sed在处理文本时,会先读取第一个输入行,将编辑命令应用于输入行,而后读取下一个输入行,并应用编辑命令。sed老是处理最新版本的行,所以sed中有多个编辑命令时,编辑命令的顺序对结果会有影响,下一个编辑命令会发生了变化的行而不是原始行,如示例: 正则表达式

[root@fanyue sed]# cat test
1 This is a pig.
2 This is a cow.
[root@fanyue sed]# sed 's/pig/cow/; s/cow/horse/' test
1 This is a horse.
2 This is a horse.bash

 能够看到sed中第二个编辑命令处理的行是被第一个命令处理以后的内容。this

模式空间

sed维护一种模式空间,即一个工做区或者临时缓冲区,当使用编辑命令时将在模式空间中存储单个输入行。一次一行的设计的有点是在读取很是庞大的文件时不会出现内存溢出或缓慢的问题。spa

初始时,模式空间包含有单个输入行的备份。而后按照命令顺序对模式空间的中的行进行处理。当应用了全部的指令后,当前行被输出,下一行被读入模式空间。而后脚本中的指令再次按顺序应用于新的行。即sed的处理步骤为:设计

  1. 生成输入行的备份到模式空间中
  2. 修改模式空间的中的备份
  3. 将修改后的备份输出到标准输出

回到上面的示例,若是我想将pig改成cow, cow改成horse改如何处理?code

[root@fanyue sed]# sed 's/cow/horse/; s/pig/cow/' test
1 This is a cow.
2 This is a horse.

 

将命令的顺序反转便可!blog

sed还维护了一个称为保持空间(hold space)的另外一个临时缓冲区,保持空间能够将模式空间的内容复制到保持空间并在之后检索它们。内存

sed的寻址

默认状况下,sed将命令用于每个行。sed命令能够指定0个,1个或2个地址。每一个地址都是一个描述模式、行号或者行寻址符号的正则表达式。class

  • 若是没有指定地址,那么命令将应用于每一行。
  • 若是只有一个地址,那么命令应用于与这个地址匹配的任意行。
  • 若是指定了由逗号分隔的两个地址,那么命令将应用于匹配第一个地址的第一行和它后面的行,直到匹配第二个地址的行(包括此行)。
  • 若是地址后面跟有感叹号(!),那么命令就应该用于不匹配该地址的全部行。

例如,d命令表明删除匹配的行,一个d命令会删除全部的行,不会有任何输出,如:test

[root@fanyue sed]# cat test
1 This is a pig.
2 This is a cow.
3 This is a dog.
4 And this is a monkey!!!
[root@fanyue sed]# sed 'd' test

 

当行号全部地址提供时,则命令只会删除匹配的那一行。例如,下面的示例只会删除第一行:

[root@fanyue sed]# sed '1d' test
2 This is a cow.
3 This is a dog.
4 And this is a monkey!!!

 

行号指由sed维护的内部行数。该计数器不会由于多个输入文件而重置。所以,无论指定多少个输入文件,1只表明输入流的第一行,若是输入流是多个文件,那么1表明第一个输入文件的第一行。

一样输入流也只有一个最后的行。可使用寻址符号$指定。下面的示例删除输入的最后一行:

[root@fanyue sed]# sed '$d' test
1 This is a pig.
2 This is a cow.
3 This is a dog.

 

$符号不要和正则表达式中的$混淆,在正则表达式做为地址提供时,这个命令只影响与这个模式匹配的行。正则表达式必须封闭在斜杠(/)中。下面的删除命令:

[root@fanyue sed]# sed '/!$/d' test
1 This is a pig.
2 This is a cow.
3 This is a dog.

 

只删除以!结尾的行。

若是提供两个地址,那么就指定了命令执行的范围。下面的示例展现了删除两个地址之间的全部行,两个地址以逗号隔开:

[root@fanyue sed]# sed '/cow/,/monkey/d' test
1 This is a pig.

 

它删除从一个模式匹配开始,到由第二种模式匹配的行(包括此行在内)为止的全部行。下面的命令删除了文件中从5行到最后一行的全部行:

[root@fanyue sed]# sed '5,$d' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

 

能够混合使用行地址和模式地址:

  1,/^$/d

sed没有办法先行判断第二个地址是否存在匹配的行,所以当命令执行后sed会从一个匹配的行开始应用命令,若是没有出现第二个匹配的行,那么将删除全部的行。

跟在地址后面的感叹号会反转匹配的意义:

[root@fanyue sed]# sed '1,2!d' test
1 This is a pig.
2 This is a cow.

 

sed使用大括号({})将一个地址嵌套在另外一个地址中,或者在相同的地址上应用多个命令。若是想指定行的范围,而后在这个范围内指定另外一个地址,则能够嵌套地址。例如:

[root@fanyue sed]# cat test
This is a pig.
-------------
This is a cow.
-------------

this is a cat.-------------This is a dog.-------------And this is a monkey!!![root@fanyue sed]# sed '/cow/,/dog/ {/^$/d; s/-/*/g}' testThis is a pig.-------------This is a cow.*************this is a cat.*************This is a dog.-------------And this is a monkey!!!

相关文章
相关标签/搜索