Linux三剑客(sed)-编辑匹配到的文本

sed:Stream Editor文本,sed是一个非交互式的面向字符流的编辑器。能同时处理多个文件多行的内容。

sed编辑器是一行一行的处理文件,正在处理的内容存放在模式空间(缓冲区)中,处理完毕后按照选项的规定进行输出或文件的修改。

sed主要用来自动编辑一个或多个文件;简化文件的反复操作,用于非交互编译文件。

1. 语法

sed [options] '[command]' [filename]

1. sed命令的选项(option)

选项 作用
-n 只打印模式匹配的行
-e 直接在命令行模式上进行sed动作编辑,此为默认选项
-f 将sed的动作写在一个文件内
-r 支持扩展表达式
-i 直接修改文件内容

2. sed命令的命令(command)

命令 作用
p 打印匹配行(和-n选项一起使用)
= 显示文件行的行号
a 在定位行号后附加新文本信息
i 在定位行号后插入新文件信息
d 删除定位行
c 用新文本替换文本
w filename 写文本到一个文件,类似输出重定向
r filename 从另一个文件中读文件,类似输出重定向
s 使用替换模式替换相应模式
q 第一个模式匹配完成后退出或立即退出
I 显示与八进制ACSII代码等价的控制符
{} 在定位行执行的命令组,用;隔开
g 将模式2粘贴到/pattern n/

2. 实战

2.1 sed在文件中查询文本方式

1. 使用行号打印特定行

可以使用一个简单的数字,或是一个行号范围

注意:p的动作是:打印匹配行。

格式 说明
xp x为行号
x,yp 表示行号从x到y
/pattern/p 查询包含模式的行
/pattern /pattern/p 查询包含两个模式的行
/pattern/,xp 包含模式和指定行号之间的行
x,/pattern/p 通过行号和模式查询匹配的行
x,y! 查询不包含指定行号x和y的行

1. 原始文件:

[newsettle@localhost userbin]$ cat exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

2. sed的默认动作
(1)sed的默认动作是打印文件中的所有行。

[newsettle@localhost userbin]$ sed '' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

3. 打印特定行
(1)因为sed命令默认打印文件中所有行。所以第三行会被打印两遍。那如何只打印第三行呢?使用【-n】命令,只打印匹配的行。

[newsettle@localhost userbin]$ sed '3p' exam.log 
#/bin/sh 

第三行111
第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(2)使用【-n】命令,只打印匹配到的行

[newsettle@localhost userbin]$ sed -n '3p' exam.log 
第三行111

(3)打印[n,m]行

[newsettle@localhost userbin]$ sed -n '3,4p' exam.log 
第三行111
第四行222

(4)打印包含模式的行

[newsettle@localhost userbin]$ sed -n '/八/p' exam.log 
END 第八行END

(5)打印包含模式和指定行号之间的行

[newsettle@localhost userbin]$ sed -n '/四/,6p' exam.log 
第四行222
第五行333
第六行444
[newsettle@localhost userbin]$ sed -n '1,/四/p' exam.log 
#/bin/sh 

第三行111
第四行222

(6)包含模式和包含模式之间的行

[newsettle@localhost userbin]$ sed -n '/三/,/四/p' exam.log 
第三行111
第四行222

(7){}执行多个命令(command),使用;隔开。=是显示文件行的行号。p是打印匹配行

[newsettle@localhost userbin]$ sed -n '1,4{=;p}' exam.log 
1
#/bin/sh 
2

3
第三行111
4
第四行222

(8)!取反操作

[newsettle@localhost userbin]$ sed -n '1,4!{=;p}' exam.log 
5
第五行333
6
第六行444
7
第七行555
8
END 第八行END
9
END 第就行END
10
第十行 3.1
11
第十一行 YES--我是真的YES 不你不YES

(9)q命令:第一个模式匹配完成后退出或立即退出,使用该命令打印前5行

[newsettle@localhost userbin]$ sed '5q' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333

2. 使用正则表达式匹配行

模式 说明
^ 锚点行首的符合条件的内容,用法格式"^pattern"
$ 锚点行尾的符合条件的内容,用法格式"pattern$"
^$ 空白行
. 匹配单个字符
* 匹配紧挨着前面字符的0次或多次
.* 匹配任意长度的任意字符
? 匹配紧挨在前面字符0次或1次
{m,n} 匹配紧挨前面字符至少m次,至多n次
{m,} 匹配紧挨前面字符至少m次
<pattern> 匹配特定单词
[] 匹配指定范围内的任意单个字符
[^] 匹配指定范围外的任意单个字符
[:digit:] 所有数字;相当于0-9,[0-9]-->[[:digit:]]
[:lower:] 所有的小写字母
[:upper:] 所有的大写字母
[:alpha:] 所有的字母
[:alnum:] 相当于0-9a-zA-Z
[:space:] 空白字符
[:punct:] 所有标点符号

(1)使用[]进行正则匹配

[newsettle@localhost userbin]$ sed -n '/[[:digit:]]/p' exam.log 
第三行111
第四行222
第五行333
第六行444
第七行555
第十行 3.1
[newsettle@localhost userbin]$ sed -n '/[1-3]/p' exam.log 
第三行111
第四行222
第五行333
第十行 3.1

(2)其他的正则表达式

sed-n '/r*t/p'/etc/passwd#打印匹配r有0个或者多个,后接一个t字符的行  
sed-n '/.r.*/p'/etc/passwd#打印匹配有r的行并且r后面跟任意字符  
sed-n '/o*/p'/etc/passwd#打印o字符重复任意次  
sed-n '/o\{1,\}/p'/etc/passwd#打印o字重复出现一次以上  
sed-n '/o\{1,3\}/p'/etc/passwd#打印o字重复出现一次到三次之间以上  

2.2 对文件的操作

对文件的操作无非就是“增改删查”,sed命令怎样实现对文件的操作呢?

1. 文件的查询

(1)打印出以#开头的行,然后用!进行反选,则表示过滤掉以#开头的行,不会过滤掉空格。

[newsettle@localhost userbin]$ sed -n '/^#/!p' exam.log 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(2)匹配以#开头的行,进行取反,则打印出非#开头的行,然后其结果在对空格开头的行进行取反。即过滤掉以#开头的行和以空格开头的行。{}表示在定位行执行的命令组。

[newsettle@localhost userbin]$ sed -n '/^#/!{/^$/!p}' exam.log 
第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(3)sed支持对单个文件实现不同的操作,每个操作用-e参数。定位到执行的行后,使用d命令,直接删除匹配到的行。

[newsettle@localhost userbin]$ sed -e '/^#/d' -e '/^$/d' exam.log 
第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

2. 文件的添加

需要注意的是,对源文件的添加要使用【-i】参数。

s:使用替换模式替换相应模式

(1)在匹配行前面替换字符,使用【s】命令。

[newsettle@localhost userbin]$ sed '/六/s/^/我是 /' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
我是 第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(2)在所有行开头替换元素【s】

[newsettle@localhost userbin]$ sed 's/^/Start /' exam.log 
Start #/bin/sh 
Start 
Start 第三行111
Start 第四行222
Start 第五行333
Start 第六行444
Start 第七行555
Start END 第八行END
Start END 第就行END
Start 第十行 3.1
Start 第十一行 YES--我是真的YES 不你不YES

(3)在所有行的末尾替换元素

[newsettle@localhost userbin]$ sed 's/$/ END/' exam.log 
#/bin/sh  END
 END
第三行111 END
第四行222 END
第五行333 END
第六行444 END
第七行555 END
END 第八行END END
END 第就行END END
第十行 3.1 END
第十一行 YES--我是真的YES 不你不YES END

(4)指定行,进行替换操作

[newsettle@localhost userbin]$ sed '3,4s/^/#/' exam.log 
#/bin/sh 

#第三行111
#第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(5)【&】符号代表的是匹配到的字符。在匹配到字符后,可以使用&代替。

[newsettle@localhost userbin]$ sed 's/第三行/你猜 &/' exam.log 
#/bin/sh 

你猜 第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES
[newsettle@localhost userbin]$ sed 's/第三行/& 你猜 /' exam.log 
#/bin/sh 

第三行 你猜 111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(6)在匹配到行前面添加一行,使用【i】的命令

[newsettle@localhost userbin]$ sed '/第四行/i 你好' exam.log 
#/bin/sh 

第三行111
你好
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES
[newsettle@localhost userbin]$ sed '/第四行/i \你好' exam.log 
#/bin/sh 

第三行111
你好
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(7)在匹配行的后面添加一行,使用【a】命令

[newsettle@localhost userbin]$ sed '/第四行/a 你好' exam.log 
#/bin/sh 

第三行111
第四行222
你好
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(8)当添加多行时,使用\n来转义

[newsettle@localhost userbin]$ sed '/第四行/a 你好\n世界' exam.log 
#/bin/sh 

第三行111
第四行222
你好
世界
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(9)@代表的是【地址定界符】,一般由三个组成,定界符可以是/,$,#等特殊字符,此命令表示,匹配特定字符的行进行替换。

[newsettle@localhost userbin]$ sed '/第三行/s@111@222@' exam.log 
#/bin/sh 

第三行222
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

需要注意的是:替换默认是修改匹配行中第一次出现的字符。

[newsettle@localhost userbin]$ sed '/YES/s@YES@NO@' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 NO--我是真的YES 不你不YES

(10)使用命令【g】修改全文中出现的匹配字符。

[newsettle@localhost userbin]$ sed '/YES/s@YES@NO@g' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 NO--我是真的NO 不你不NO

(11)若后面接数字之后在接g,表示匹配的行中,第几次出现。就替换,2g表示替换行中第二次出现。

[newsettle@localhost userbin]$ sed '/YES/s@YES@NO@2g' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的NO 不你不NO

3. 文件行的删除

(1)删除以非#号开头的行,即显示以#号开头的行。

[newsettle@localhost userbin]$ sed '/^#/!d' exam.log 
#/bin/sh 

(2)删除第一行

[newsettle@localhost userbin]$ sed '1d' exam.log 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(3)删除最后一行

[newsettle@localhost userbin]$ sed '$d' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1

(4)删除指定的行区间

[newsettle@localhost userbin]$ sed '3,5d' exam.log 
#/bin/sh 

第六行444
第七行555
END 第八行END
END 第就行END
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

(5)删除包含特定单词的行

[newsettle@localhost userbin]$ sed '/\<END\>/d' exam.log 
#/bin/sh 

第三行111
第四行222
第五行333
第六行444
第七行555
第十行 3.1
第十一行 YES--我是真的YES 不你不YES

本文参考:
sed命令详解

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • grep擅长查找,awk擅长分析(select),sed擅长批量编辑行 概述 SED的英文全称是 Stream E...
    piziyang12138阅读 941评论 0 3
  • grep擅长查找,awk擅长分析(select),sed擅长批量编辑行概述SED的英文全称是 Stream EDi...
    Arroganter阅读 1,089评论 0 7
  • 一、前言 我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件等等。如果我们相对这些文件进行一些...
    以七v为书阅读 1,544评论 0 5
  • 简介 sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(p...
    699b979fc4da阅读 1,029评论 0 1
  • 噢我为啥要学python 我也不懂 我vue还没学清楚啊 (ノ`Д)ノ算了学吧主要参考:廖雪峰的python教程h...
    杨肆月阅读 181评论 0 0