Linux sed命令详解

Sed是一个强大的文本处理工具,可以采用正则匹配,对文本进行插入删除修改等操作。

简介

Sed是一个强大的文本处理工具,可以采用正则匹配,对文本进行插入删除修改等操作。
Sed处理的时候,一次处理一行,每一次把当前处理的存放在临时缓冲区,处理完后输出缓冲区内容到屏幕,然后把下一行读入缓冲区,如此重复,直到结尾。

命令格式与参数

sed [-nefr] [动作] 文件
参数:

-n 安静模式,在sed处理的时候,所有来自STDIN的数据都会被输出到终端,加上-n会只输出处理的哪行
-e 直接在命令列上进行sed动作编辑
-f 直接将sed的动作写在文件内
-r sed动作支持延伸的正则表达(默认只是基础正则)
-i 直接修改文件内容(慎用,尤其是用系统文件做练习的时候)

动作:

a append:增加,在当前行的下一行增加
c :取代,取代n1到n2之间的行
d delete:删除
i 插入,目前行的上一行插入
p 打印,常常与-n使用
s 取代,s/old/new/g

基础用法详解

(1)第一行之后添加一行

1
2
3
4
5
6
[root@localhost ~]# nl file.txt | sed "1a add text"
1 wtmp begins Mon Feb 24 14:26:08 2014
add text
2 192.168.0.1
3 162.12.0.123
4 this is the last line

(2)第一行之前添加一行

1
2
3
4
5
6
[root@localhost ~]# nl file.txt | sed "1i add text"
add text
1 wtmp begins Mon Feb 24 14:26:08 2014
2 192.168.0.1
3 162.12.0.123
4 this is the last line

(3)删除第2,3行

1
2
3
[root@localhost ~]# nl file.txt | sed "2,3d"
1 wtmp begins Mon Feb 24 14:26:08 2014
4 this is the last line

(4)打印第2,3行

1
2
3
[root@localhost ~]# sed -n "2,3p" file.txt
192.168.0.1
162.12.0.123

(5)把168换成169
先看源文件

1
2
3
4
5
[root@localhost ~]# cat file.txt
wtmp begins Mon Feb 24 14:26:08 2014
192.168.0.1
162.12.0.123
this is the last line

处理后

1
2
3
4
5
[root@localhost ~]# sed "s/168/169/g" file.txt
wtmp begins Mon Feb 24 14:26:08 2014
192.169.0.1
162.12.0.123
this is the last line

(6)插入多行

1
2
3
4
5
6
7
[root@localhost ~]# nl file.txt | sed "2afirst\nsecond" file.txt
wtmp begins Mon Feb 24 14:26:08 2014
192.168.0.1
first
second
162.12.0.123
this is the last line

(7)匹配数据,然后进行操作
只需要在上述的基础上加上正则匹配
sed “/匹配的模式/处理的方式” file.txt
sed “/^root/d” file.txt 对开始有root的删除
例如:匹配begin,并删除改行

1
2
3
4
[root@localhost ~]# nl file.txt | sed "/begin/d"
2 192.168.0.1
3 162.12.0.123
4 this is the last line

匹配123,并且把含有123的行162都替换成172

1
2
3
4
5
[root@localhost ~]# nl file.txt | sed "/123/{s/162/172/g;q}"
1 wtmp begins Mon Feb 24 14:26:08 2014
2 192.168.0.1
3 172.12.0.123
4 this is the last line

这里大括号{}里可以执行多个命令,用;隔开即可,q是退出

(8)连续编辑 -e
删除第二行,并且匹配把last替换成new

1
2
3
4
5
6
[root@localhost ~]# sed -i "/begin/{s/24/25/g}" file.txt
[root@localhost ~]# cat file.txt
wtmp begins Mon Feb 25 14:26:08 2014
192.168.0.1
162.12.0.123
this is the last line

(9)直接修改文件,切记不要修改系统文件

1
2
3
4
5
6
[root@localhost ~]# sed -i "/begin/{s/24/25/g}" file.txt
[root@localhost ~]# cat file.txt
wtmp begins Mon Feb 25 14:26:08 2014
192.168.0.1
162.12.0.123
this is the last line

linux sed命令,如何替换换行符“\n”

执行命令:

1
sed "s/\n//g" file

发现,没起到任何效果。后来,经查sed官方用户手册,才得知,sed是按行处理文本数据的,每次处理一行数据后,都会在行尾自动添加trailing newline,其实就是行的分隔符即换行符。
如果非要使用sed命令,实现替换file文本内容的换行符为空的话,那么就要了解sed的分支条件命令,以及了解sed的pattern space模式空间和hold space保持空间。即,连续两行执行一次sed命令,这样就可以把前一行的\n替换完成。

实现方法

第一种方法:使用test跳转命令,实现替换换行符

1
sed ":a;N;s/\n//g;ta" a.txt

N是把下一行加入到当前的hold space模式空间里,使之进行后续处理,最后sed会默认打印hold space模式空间里的内容。也就是说,sed是可以处理多行数据的。
:a和ta是配套使用,实现跳转功能。t是test测试的意思。
另外,还有:a和ba的配套使用方式,也可以实现跳转功能。b是branch分支的意思。

branch和test区别

branch循环到文本结束。比如sed “:a;N;s/\n//g;ba” a.txt,转换成自然语言的描述,就是

1
2
3
4
while(1) {
N;
s/\n//g;
}

test可以根据替换命令的完成是否成功,决定是否跳转。比如sed “:a;N;s/\n//g;ta” a.txt,转换成自然语言的描述,就是

1
2
3
4
5
6
7
while(state == 1) { #注释:默认state就当是1好了。
N;
s/\n//g;#注释:成功,返回state为1;否则返回state=0。此state用于跳转判断。
}
else {
last; #注释:即退出循环语句。
}

第二种方法:使用branch跳转命令,实现替换换行符

1
sed ":a;N;s/\n//g;$!ba" a.txt

增加$!ba语句,$的意思是最后一行,不跳转到标记a处,即退出命令循环。
同理,也可以用下述命令。

1
sed ":a;$!N;s/\n//g;ba" a.txt

Windows与Linux中的换行符差异

Unix系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<换行><回 车>”,即“\n\r”。一个直接后果是,Unix系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在 Unix下打开的话,在每行的结尾可能会多出一个^M符号。

文件的每行末尾都有^M符号,这通常是看不出来的。可以用”cat -A test.file”命令查看。因此当我想在行尾添加字符的时候,它总是添加在行首且会覆盖掉原来行首的字符。

要把文件转换一下,有两种方法:
1.命令dos2unix test.file
2.去掉”\r” ,用命令sed -i ‘s/\r//‘ test.file

参考链接:
【1】Linux Sed命令详解+如何替换换行符”\n”
【2】linux sed命令,如何替换换行符“\n”
【3】linux shell 用sed命令在文本的行尾或行首添加字符