sed命令简介


发布于 2016-07-15 / 64 阅读 / 0 评论 /
sed称为流编辑器(stream editor),是Linux世界中使用最广泛的编辑器之一,也是Linux三剑客之一。

1.sed工具概述

sed称为流编辑器(stream editor),是Linux世界中使用最广泛的编辑器之一。流编辑器会在处理数据之前预先提供一组规则来编辑数据。这些规则即可以直接写在命令行中,也可以写在文件中。

1.1.sed处理流程

sed编辑器的处理流程如下:

(1)第一步,一次从输入中读取一行数据;

(2)第二步,根据所提供的编辑器命令匹配数据;

(3)第三步,按照命令修改流中的数据;

(4)第四步,将新的数据输出到STDOUT。

流程可用下图表示。

1.2.sed命令行格式

sed基本命令行格式如下:

sed options script file

其中,options可选值如下表所示:

option

功能描述

案例

-e script

在处理输入时,将script中指定的命令添加到已有的命令中 ,命令之间必须用分号分隔开,并且一条命令的末尾和分号之间不能有空格。

将data1.txt文件中的brown替换为green,将dog替换为cat。

sed -e 's/brown/green/; s/dog/cat/' data1.txt

-f file

在处理输入时,将file中指定的命令添加到已有的命令中。

sed -f script1.sed data1.txt

-n

不产生命令输出,使用print来完成输出,只打印指定或者匹配的行。

2.sed基本功能

sed有六个基本的功能,分别为:替换(s,substitute),删除(d,delete),插入(i,insert),附加(a,append),修改(c,change),转换(y,transform)。下面分别对这六种功能进行解析。

2.1.替换

sed最常用的功能是替换,替换命令格式为:

s/pattern/replacement/flags

一般来说,“/”作为分隔符,但是如果“/”在pattern或replacement中被使用,则“/”分隔符可以被其他字符替代。例如:

echo "asdflls" | sed -e 's|asdf|bbbb|'

上述案例用“|”来替代分隔符。

flags有四种模式,如下表所示:

flag

描述

案例

数字

表明替换作用在第几处匹配的地方

g

新文本将会替换所有匹配的文本

p

原先行内容要打印出来

w file

将替换结果写到文件中

sed 's/test/trial/w test.txt' data5.txt

很多情况下,我们只需要对指定的行进行操作,sed提供了寻址的功能,可以通过数字(从1开始)来指定某些行,也可以通过文本过滤器来匹配行数据。对于数字指定行,可以在命令行中出现单个数字(特殊地址符为$,表示最后一行)表示某一行。例如:

# 第2行进行替换
sed '2s/dog/cat/' data.txt

也可以出现两个数字表示行区间,例如:

# 从第2行到最后一行进行替换
sed '2,$s/dog/cat/' data.txt

文本过滤器格式为“/pattern/command”,例如:

# 从/etc/passwd筛选出helloworld的行数据进行替换操作
sed '/helloworld/s/bash/csh/' /etc/passwd

选址可作用于单个命令,也可以作用于多个命令,命令行格式如下表所示。

选址命令格式

说明

address[command]

选址对应于单个命令

address {

command1

command2

……

}

选址对应于多个命令

2.2.删除

sed还有一个常用的功能——d命令。sed可以根据上面的选址功能对相应的行数据进行删除。模式匹配删除时需要特别注意,可以用两个模式来删除某个区间内的行,指定的第一个模式会“打开”行删除功能(开始模式),第二个模式会“关闭”行删除功能(停止模式),如果只匹配到了开始模式,而没有匹配到停止模式,则删除功能会一直进行删除。例如下图所示。

还可以使用相对行数的选址模式来对行数据进行删除。比如:

# 查找到dog数据行进行删除,并往后3行也删除
sed '/dog/,+3d' data.txt

# 从第一行开始,每隔一行删除,即删除第2、5、8……行
sed '2~3d' data.txt

2.3.插入和附加

插入(insert)命令(i)会在指定行前插入一行新数据。附加(append)命令(a)会在指定行后插入一行新数据。命令行格式如下(new line将会出现在指定的位置):

sed '[address]command\
new line'

使用案例如下图所示:

注意,如果要插入和附加多行,在每一行前面加“\”符号。案例如下图所示:

2.4.修改

修改(change)命令允许修改数据流中的整行文本内容,即可以修改一行,也可以修改多行。案例如下图所示。图中左边第一个案例表示把第二行修改为“this is a new line”;第二个案例表示把第1到3行修改为一行数据“this is a new line”。图中右边的案例都是以字符匹配来寻址,对符合条件的每一行都会进行修改。

2.5.转换

转换(transform)命令(y)是唯一可以处理单个字符的sed编辑器命令,命令格式为:

[address]y/inchars/outchars/

转换命令会对inchars和outchars的值进行一对一的映射,如果inchars和outchars的字符长度不一致,sed编辑器会产生一条错误信息。案例如下图所示。

2.6.打印

sed中有三个命令可用于打印数据流中的信息:

(1)p命令打印文本行;

(2)等号(=)命令用了打印行号;

(3)l(小写的L)命令用来列出行。

p命令用来打印sed输出的每一行,如果使用-n选项,则只打印包含匹配文本模式的行。案例如下图所示。

l命令用来打印数据流中的文本和不可打印的ASCII字符,任何不可打印的字符要么在其八进制值前加一个反斜线,要么使用标准C风格的命名法,行尾用美元符表示换行符。

3.使用sed处理文件

我们可以使用sed对文件进行读和写。

其中,w命令用来向文件中写入行数据,命令格式为:

[address]w filename

案例如下图所示,将data2.txt文件的第2到3行写入data1.txt,这种写如是覆盖式的。

r命令用来将文件中的数据插入到数据流中,命令格式为:

[address]r filename

案例如下图所示,将data2.txt的数据作为数据流,并在第一行数据之后插入data1.txt文件的数据。

4.sed进阶

以上讲述了sed的基本用法,一般情况下,可以满足我们的使用需求。此外,sed还提供了其他更高级的使用方法。下面分别进行描述。

4.1.多行命令

之前我们讲述的sed命令都是基于单行进行处理的。但是,sed具备多行数据的处理功能,sed编辑器有三个可用来处理多行文本的特殊命令 :

(1)N——将数据流的下一行加进来构建一个多行组(multiline group);

(2)D——删除多行组中的一行;

(3)P——打印多行组中的一行。

4.1.1.next命令

单行next命令(小写n)会将数据流中的下一文本行移动到sed编辑器的工作空间(称为模式空间)。多行版本的next命令(用大写N)会将下一文本行添加到模式空间中已有的文本后。

上述是next命令的替换案例中。data.txt的处理是单行命令,把带有orange单词的下一行删除。data1.txt的处理是多行命令,把“sunny.day”替换成“good day”,其中“.”是通配符。

上图是next命令的删除案例。对data.txt的处理是找到空行,并把下一行加入模式空间,用orange匹配,如果匹配到,则把这个空行删除。对data1.txt的处理是“d”和“D”的区别,用d命令会把匹配到的两行都删除,而D命令则只会把模式空间中的第一行删除。

4.1.2.模式空间和保持空间

模式空间(pattern space)是一块活跃的缓冲区,在sed编辑器执行命令时会保存待检查的文本。保持空间(hold space)也是一块活跃的缓冲区,在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。对保持空间的操作命令如下表所示。

命令

说明

h

将模式空间复制到保持空间

H

将模式空间附加到保持空间

g

将保持空间复制到模式空间

G

将保持空间附加到模式空间

x

交换模式空间和保持空间的内容

案例如下图所示。

4.1.3.排除命令

排除命令用感叹号(!)来表示,也就是让原先起作用的命令不起作用。案例如下图所示,左边的案例表示不打印包含banana单词的行数据。右边的表示对对data.txt文件中的行逆序打印,和tac命令的作用是一致的(tac与cat在拼写以及作用上都是相反的)。

4.2.改变流

一般来说,sed会从脚本的顶部开始处理,一直执行到最后一行。sed编辑器提供了一个方法来改变命令脚本的执行流程,其结果与结构化编程类似。这种方法是b命令和t命令,其中b命令基于地址、地址模式或地址区间来进行跳转,而t命令根据上一条命令的结果来决定跳转。

4.2.1.b命令

b命令行格式为:

[address]b [label]

其中address决定了哪些行的数据会触发b命令。label参数定义了要跳转到的位置,如果没有加label参数,则命令会跳转到脚本的结尾。

案例如上图所示,左边的案例表示无label的命令,第2到3行数据不执行替换命令。右边的是代label的命令。

我们还可以使用sed的b命令来构成循环,如下图所示:

第一种情况,因无指定地址,b命令会一直执行,构成死循环,而第二种情况,指定了匹配条件,如果查找不到“,”则不会执行b命令。

4.2.2.t命令

t命令的命令行格式和b命令一致

[address]t [label]

如果测试成功,则t命令会直接跳转到脚本的尾部,测试失败,则会继续执行t命令之后的脚本。案例如下图所示:

左边的案例是无label情况,如果第一条替换命令执行成功,则不会执行t命令后面的替换命令;如果第一条命令匹配失败,无法替换,则会执行t命令后面的替换命令。

右边的案例是有label的情况,循环替换行数据的逗号。

根据以上案例可以看出,t命令其实和if-else的逻辑是一致的,只有当t命令之前的命令匹配失败才会执行t命令之后的脚本或命令。

4.3.模式替代

以上介绍的sed的替换命令都是覆盖式的替换,即把匹配到的模式用其他的具体的单词覆盖。很多时候,我们需要修改式的替换,即在原来的单词基础上进行修改。为此,sed提供了一个解决方案——&符号。替代模式中,可以使用&来代替匹配到的单词。案例如下图所示:

其中“.”是通配符,可匹配任意字符。

上图中第一个案例把ood结尾的四字符单词加上双引号。

第二个案例把that furry hat替换成my cat。

第三个案例给数字进行三位分隔。

第二、三个案例都用到了子模式,“\1”和“\2”指第一个和第二个子模式匹配到的字符串。如果有多个子模式,可同理递推。