上古神器 sed 教程详解,小白也能看得懂
介绍
熟悉 Linux 的同学一定知道大名鼎鼎的 Linux 三剑客,它们是 grep
、awk
、sed
,我们今天要聊的主角就是 sed
。
sed 全名叫 stream editor
,流编辑器,用程序的方式来编辑文本,与 vim 的交互式编辑方式截然不同。它的功能十分强大,加上正则表达式的支持,可以进行大量的复杂文本的编辑操作。
实际上 sed 提供的功能非常复杂,有专门的书籍讲解它。本文不会讲 sed 的全部东西,只会从 sed 的工作原理、常见使用方法等方面进行说明和讲解,同时也会给出大量的实践用例来帮助更好的理解 sed 基本用法。文中的知识点真正掌握后,足以应付平时工作中的基本需求。
它有自己的使用场景:
自动化程序中,不适合交互方式编辑的;
大批量重复性的编辑需求;
编辑命令太过复杂,在交互文本编辑器难以输入的情况;
工作原理
sed 作为一种非交互式编辑器,它使用预先设定好的编辑指令对输入的文本进行编辑,完成之后输出编辑结果。
简单描述 sed 工作原理:
sed 从输入文件中读取内容,每次处理一行内容,并把当前的一行内容存储在临时的缓冲区中,称为
模式空间
。接着用 sed 命令处理缓存区中的内容;
处理完毕后,把缓存区的内容送往屏幕;
接着处理下一行;
这样不断重复,直到文件末尾,文件内容并没有改变,除非你使用重定向输出或指定了 i
参数
正则表达式
sed 基本上就是在玩正则表达式模式匹配,所以,会玩 sed 的人,正则表达式能力一般都比较强。正则表达式内容相对较多,本节不会重点讲解正则表达式。
为了能够让大部分朋友比较轻松地学习本文知识,这里还是简单介绍下正则表达式的基本内容。如果是专门做正则编程开发的,可以去买本正则的书籍来看。
(一)基本正则表达式
.
,表示匹配任意一个字符,除了换行符,类似 Shell 通配符中的?
;*
,表示前边字符有 0 个或多个;.*
,表示任意一个字符有 0 个或多个,也就是能匹配任意的字符;^
,表示行首,也就是每一行的开始位置,^abc
匹配以 abc 开头的字符串;$
,表示行尾,也就是每一行的结尾位置,}$
匹配以大括号结尾的字符串;{}
,表示前边字符的数量范围,{2}
,表示重复 2 次,{2,}
重复至少 2 次,{2,4}
重复 2-4 次;[]
,括号中可以包含表示字符集的表达式,使用方法大概如下几种
(二)扩展正则表达式
扩展正则表达式使用频率上没有基本表达式那么高,但依然很重要,很多情况下没有扩展正则是搞不定的,sed 命令使用扩展正则时需要加上选项 -r
。
?
:表示前置字符有 0 个或 1 个;+
:表示前置字符有 1 个或多个;|
:表示匹配其中的一项即可;()
:表示分组,(a|b)b
表示可以匹配 ab 或 bb 子串,且命令表达式中可以通过\1
、\2
来表示匹配的变量{}
:和基本正则中的大括号中意义相同,只不过使用时不用加 转义符号;
基本语法
先介绍下 sed 的基本语法。
sed [选项] 'command' filename
选项部分,常见选项包括:-n
、-e
、-i
、-f
、-r
等。
command 子命令格式:
[地址1, 地址2] [函数] [参数(标记)]
选项简单说明:
-n
,表示安静模式。默认 sed 会把每行内容处理完毕后打印到屏幕上,加上选项后就不会输出到屏幕上。-e
,如果需要用 sed 对文本内容进行多种操作,则需要执行多条子命令来进行操作;-i
,默认 sed 只会处理模式空间的副本内容,不会直接修改文件,如果需要修改文件,就要指定-i
选项;-f
,如果命令操作比较多时,用-e
会有点力不从心,这时需要把多个子命令写入脚本文件,使用-f
选项指定执行该脚本;-r
:如果需要支持扩展正则表达式,那么需要添加-r
选项;
数字定址和正则定址
默认情况下 sed 会对每一行内容进行匹配、处理、输出,有时候我们不需要对所有内容进行操作,只需要修改一种一部分,比如 1-10 行,偶数行,或包括 hello 字符串的行。
这种情况下,就需要我们去定位特定的行来进行处理,而不是全部内容,这里把定位指定的行叫做 定址。
(一)数字定址
数字定址其实就是通过数字去指定要操作的行,有几种方式,每种方式都有不同的应用场景。
(二)正则定址
正则定址,是通过正则表达式的匹配来确定需要处理编辑哪些行,其它行就不需要处理
(三)数字定址和正则定址混用
数字定址和正则定址可以配合使用
基本子命令
(一)替换子命令 s
子命令 s
为替换子命令,是平时 sed 使用最多的命令,因为支持正则表达式,功能很强大,基本可以替代 grep
的基本用法。
基本语法:
[address]s/pat/rep/flags
替换子命令基本用法
正则表达式的简单使用
多个匹配
使用匹配到的变量
其它几个常见用法
注意,sed 修改匹配到的内容后,默认行为是不保存到原文件,直接输出修改后模式空间的内容,如果要修改原文件需要指定 -i
选项。
(二)追加行子命令 a
子命令 a
表示在指定行下边插入指定的内容行;
(三)插入行子命令 i
子命令 i
和 a
使用基本一样,只不过是在指定行上边插入指定的内容行
(四)替换行子命令 c
子命令 c
是表示把指定的行内容替换为自己需要的行内容
(五)删除行子命令 d
子命令 d
表示删除指定的内容行,这个很容理解
(六)设置行号子命令=
子命令 =
,可以将行号打印出来
(七)子命令 N
子命令 N
,把下一行内容纳入当缓存区做匹配,注意的是第一行的 \n
仍然保留
其实就是当前行的下一行内容也读进缓存区,一起做匹配和修改,举个例子吧
哈哈,是不是很简单?
实战练习
掌握了上边的基础命令操作后,基本上可以满足平时 95%
的需求啦。sed 还有一些高级概念,比如:模式空间、保持空间、高级子命令、分支和测试等,平时使用概率非常小,本文就暂不讲解了,有需要的同学可以私信我一起交流学习哈。
学习了这么多基础用法后,只要你勤加练习,多实践,多使用,一定可以得心应手,极大提高的文本处理效率。下边我简单再给出一些比较实用的操作实践,希望对大家有帮助。
1. 删除文件每行的第二个字符
2. 交换每行的第一个字符和第二个字符
3. 删除文件中所有的数字
4. 用制表符替换文件中出现的所有空格
5. 把所有大写字母用括号()括起来
6. 隔行删除
7. 删除所有空白行
好了,以上是 sed 命令常用的全部内容。想要熟练掌握,只有多实践,多练习正则表达式的使用,一旦熟练掌握后,相信在日后工作中一定会产生巨大作用的。
谢谢大家,我是肖邦,欢迎关注后续的精彩内容。
推荐阅读:
版权声明: 本文为 InfoQ 作者【程序员肖邦】的原创文章。
原文链接:【http://xie.infoq.cn/article/6d6e9cdf3988d450a1cf5eb37】。文章转载请联系作者。
评论