一、流编辑器 sed 与命令 sed

  Linux 中,常使用流编辑器 sed 进行文本替换工作。与常使用的交互式编辑器(如vim)不同,sed 编辑器以批处理的方式来编辑文件,这比交互式编辑器快得多,可以快速完成对数据的编辑修改。

  一般来说,sed 编辑器会执行以下操作:

1)一次从输入中读取一行数据;

2)根据所提供的编辑器命令匹配数据;

3)按照命令修改流中的数据;

4)将新的数据输出到 STDOUT。

  在 sed 编辑器匹配完一行数据后,它会读取下一行数据并重复这个过程,直到处理完所有数据。使用 sed 命令打开一个 sed 编辑器。sed 命令的格式如下:

sed [options] edit_commands [file]    # [ ] 中的内容为可选可不选

  其中,options 为命令选项,选择不同的 options 可以修改 sed 命令的行为,主要有 3 个选项:

1)-e 选项: 在处理输入时,将 script 中指定的编辑命令添加到已有的命令中。通俗的说,就是在 sed 后面直接添加编辑命令:

sed -e 'edit_commands' [files]

  sed 命令在默认情况下使用的是 -e 选项。当只有一个编辑命令时,-e 选项可以省略;但是当要在一条 sed 语句中执行多个编辑命令时,就需要使用 -e 选项了:

sed -e 's/root/ROOT/g; s/bin/BIN/g' /etc/passwd       # 使用 sed 同时执行两条编辑命令(本文大部分用例都直接使用 /etc/passwd 文件)

sed -e 's/root/ROOT/g' -e 's/bin/BIN/g' /etc/passwd   # 使用 sed 同时执行两条编辑命令

2)-f 选项:在处理输入时,将 file 中指定的编辑命令添加到已有的命令中:

  前面提到,在需要同时执行多条编辑命令时,可以使用 -e 选项。但是当所需要执行的编辑命令数量很多时,每次使用 sed 时一行一行地敲显然不是很方便,这时可以将所用到的 sed 编辑命令写入一个文件,然后使用 sed -f 选项来指定读取该文件:

$ cat script.sed
$ s/root/ROOT/
$ s/bin/BIN/
$ s/home/HOME/
sed -f script.sed /etc/passwd

3)-n 选项: 不产生命令输入:

sed -n 's/root/ROOT/' /etc/passwd

  使用 -n 选项不会将流编辑器的内容输出到 STDOUT,通常将 -n 选项与 p 命令结合起来使用,以只打印被匹配的行。

  除了这三个选项外,sed 编辑器还提供了许多命令,用来进行更详细的操作,简单列一下,后面再仔细介绍:

命令 描述
s 文本替换操作
d 删除操作
i 插入操作
a 附加操作
c 将一行文本修改为新的行
y 逐字符替换
p 打印文本行
= 打印行号
w 向文件中写入数据
r 从文件中读取数据

二、使用 sed 命令进行文本替换

  sed 使用 s 命令来进行文本替换操作,基本格式如下:

sed 's/srcStr/dstStr/' file

  其中,srcStr 为想要替换的文本,dstStr 为将要替换成的文本。使用 s 命令时,sed 编辑器会在一行一行地读取文件 file,并在每行查找文本 srcStr,如果找到了,则将该处的 srcStr 替换为 dstStr。

  / 字符为界定符,用于分隔字符串(sed 编辑器允许使用其他字符作为替换命令中的字符串分隔符):

sed 's!/bin/bash!/BIN/BASH!' /etc/passwd    # 使用 ! 作为字符串分隔符

  默认情况下,替换命令只会替换掉目标文本在每行中第一次出现的地方。若想要替换掉每行中所有匹配的地方,可以使用替换标记 g。替换标记放在编辑命令的末尾。除了 g 外,还有几种替换标记:

1)数字:指明替换掉第几次匹配到的文本,没有设置这个标记时,默认是替换第一次匹配的文本:

sed 's/root/ROOT/2' /etc/passwd

  这行命令将 /etc/passwd 文件中每行的第 2 个 root 替换为 ROOT;

2)g :替换所有匹配到的文本:

sed 's/root/ROOT/g' /etc/passwd

  这行命令将 /etc/passwd 文件中的 root,全部替换为 ROOT;

3)p :打印与替换命令中指定模式(srcStr)相匹配的行:

sed 's/root/ROOT/p' /etc/passwd

  执行这命令,会在 STDOUT 上看到包含有 root 的行被输出了两次,一次是 sed 编辑器自动输出的;另一次则是 p 标记打印出来的匹配行。

  单独地使用 p 标记没什么用处,通常将 p 标记和 -n 选项结合起来使用,这样就可以只输出被匹配替换过的行了:

sed -n 's/root/ROOT/gp' /etc/passwd    # 将 /etc/passwd 中所有的 root 都替换成 ROOT,并输出被修改的行

  注:可以使用 " = " 命令来打印行号,用法与 p 一样。  

4)w file :将替换的结果写到文件中,不过只保存被修改的行,与 -n + p 的功能类似:

sed -n 's/root/ROOT/g w change.txt' /etc/passwd     # 将 /etc/passwd 中所有的 root 都替换成 ROOT,并将被修改的行保存到文件 change.txt 中去

三、使用行寻址对特定行进行编辑

  默认情况下,sed 编辑器会对文件中的所有行进行编辑。当然,也可以只指定特定的某些行号,或者行范围来进行流编辑,这需要用到行寻址。所指定的行地址放在编辑命令之前:

[address] commands

3.1 使用数字方式进行行寻址

  sed 编辑器将文本流中的每一行都进行编号,第一行的编号为 1 ,后面的按顺序分配行号。通过指定特定的行号,可以选择编辑特定的行。举几个例子:

sed '3 s/bin/BIN/g' /etc/passwd    # 将第3行中所有的 bin 替换成 BIN
sed '2,5 s/bin/BIN/g' /etc/passwd   # 将第2到5行中所有的 bin 替换成 BIN sed '10,$ s/bin/BIN/g' /etc/passwd  # 将第10行到最后一行中所有的 bin 替换成 BIN

  注:行寻址不止对替换命令有效,对其他命令也都是有效的,后面也会用到。

3.2 使用文本模式过滤器过滤行

  sed 编辑器允许指定文本模式来过滤出命令要作用的行,格式如下:

/pattern/command

  必须使用斜杠符 " / " 将要指定的文本模式 pattern 包含起来。sed 编辑器会寻找匹配文本模式的行,然后对这些行执行编辑命令:

sed -n '/root/s/bin/BIN/p' /etc/passwd    # 寻找包含有字符串 root 的行,并将匹配行的 bin 替换为 BIN

  与数字寻址一样,也可以使用文本过滤区间来过滤行:

sed '/pattern1/,/pattern2/ edit_command' file

  这行命令会在文件 file 中先寻找匹配 pattern1 的行,然后从该行开始,执行编辑命令,直到找到匹配 pattern2  的行。但是需要注意的是,使用文本区间过滤文本时,只要匹配到了开始模式(pattern1),编辑命令就会开始执行,直到匹配到结束模式(pattern2),这会导致一种情况:一个文本中,先匹配到了一对 pattern1、pattern2,对该文本区间中的文本执行了编辑命令;然后,在 pattern2 之后又匹配到了 pattern1,这时就会再次开始执行编辑命令,因此,在使用文本区间过滤时要格外小心。举个例子:

sed -n '/root/,/nologin/ s/bin/BIN/p' /etc/passwd

  这行命令对 /etc/passwd 进行了两次文本区间匹配,结果如下:

  

四、使用 sed 命令删除行

  sed 编辑器使用 d 命令来删除文本流中的特定行。使用 d 命令时,一般需要带上位寻址,以删除指定的行,否则默认会删除所有文本行:

sed '/root/d' /etc/passwd   # 删除匹配 root 的行

sed '2,$d' /etc/passwd    # 删除第2到最后一行

五、使用 sed 命令插入和附加文本

  sed 编辑器使用 i 命令来向数据流中插入文本行,使用 a 命令来向数据流中附加文本行。其中:i 命令会在指定行前增加一个新行;a 命令会在指定行后增加一个新行。

  需要注意的是,这两个命令都不能在单个命令行上使用(即不是用来在一行中插入或附加一段文本的),只能指定插入还是附加到另一行。命令格式如下:

sed '[address][i | a]\newline' file

  newline 中的文本即为将要插入或附加在一行前面或后面的文本。常常使用这两个命令结合行寻址在特定的行前面或后面增加一个新行。举个例子:

sed 'i\Insert a line behind every line' /etc/passwd      # 向数据流的每一行前面增加一个新行,新行的内容为 \ 后面的内容

sed '1i\Insert a line behind the first line' /etc/passwd   # 在数据流的第一行前面增加一个新行

sed '3a\Append a line after the third line' /etc/passwd      # 在数据流的第三行后面增加一个新行
    
sed '$a\Append a line in the last line' /etc/passwd      # 在数据流的最后一行后面增加一个新行

六、使用 sed 命令修改行

  使用命令 c 可以将数据流中的整行文本修改为新的行,与插入、附加操作一样,这要求在 sed 命令中指定新的行,格式如下:

sed '[address][c]\newtext' file

  newtext 中的文本为匹配行将要被修改成的文本。

sed '3 c\New text' /etc/passwd     # 将数据流中第三行的内容修改为 \ 后面的内容

sed '/root/ c\New text' /etc/passwd  # 将匹配到 root 的行的内容修改为 \ 后面的内容

sed '2,4c\New text' /etc/passwd     # 将第2到4行的内容修改为 \ 后面的内容,但是不是逐行修改,而是会将这之间的  行用一行文本来替代

  注意这里对地址区间使用 c 命令进行修改时,不会逐行修改,而是会将整个区间用一行修改文本替代。

七、使用 sed 命令逐字符转换

  使用 y 参数可以按要求对文本进行逐字符转换。格式如下:

[address]y/inchars/outchars/

  转换命令会对 inchars 和 outchars 的值进行一对一的映射。inchars 中的第一个字符会被转换成 outchars 中的第一个字符;inchars 中的第二个字符会被转换成 outchars 中的第二个字符;... 直到处理完一行。如果 inchars 和 outchars 的长度不同,则 sed 编辑器会产生一个错误消息。举个例子:

echo abcdefggfedcba | sed 'y/acg/ACG/'

  输出结果为 AbCdefGGfedCbA。

八、使用 sed 命令处理文件

8.1 向文件中写入数据

  前面已经提到过,可以使用 w 命令向文件写入行。格式如下:

[address]w filename

  举个例子:

sed '1,2w test.txt' /etc/passwd

  该语句将数据流的第 1、2 行写入文件 test.txt 中去。

8.2 从文件中读取数据

  可以使用 r 命令来将一个文本中的数据插入到数据流中去,与普通的插入命令 i 类似,这也是对行进行操作的,命令格式如下:

[address]r filename

  filename 为要插入的文件。r 命令常结合行寻址使用,以将文本插入到指定的行后面。举个例子:

sed '3 r test.txt' /etc/passwd

  这句话将文件 test.txt 中的内容插入到数据流第三行后面去。

参考书籍:

《Linux命令行与shell脚本编程大全》 (第3版)

《Shell脚本学习指南》

Shell 基础 -- 流编辑器 sed 详解的更多相关文章

  1. Linux Shell编程与编辑器使用详解

    <Linux Shell编程与编辑器使用详解> 基本信息 作者: 刘丽霞 杨宇 出版社:电子工业出版社 ISBN:9787121207174 上架时间:2013-7-22 出版日期:201 ...

  2. Linux下的sed流编辑器命令详解

    sed是stream editor的简称,也就是流编辑器.它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内 ...

  3. Shell脚本学习之sed详解

    在编写shell脚本的过程中,我们经常需要使用sed流编辑器和awk对文本文件进行处理. 一.什么是sed? sed 是一种在线编辑器,它一次处理一行内容.sed是非交互式的编辑器.它不会修改文件,除 ...

  4. hbase shell基础和常用命令详解(转)

    HBase shell的基本用法 hbase提供了一个shell的终端给用户交互.使用命令hbase shell进入命令界面.通过执行 help可以看到命令的帮助信息. 以网上的一个学生成绩表的例子来 ...

  5. hbase shell基础和常用命令详解

    HBase是Google Bigtable的开源实现,它利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为协同服 ...

  6. sed 详解

    sed 详解 1.简介 sed是非交互式的编辑器.它不会修改文件,除非使用shell重定向来保存结果.默认情况下,所有的输出行都被打印到屏幕上. sed编辑器逐行处理文件(或输入),并将结果发送到屏幕 ...

  7. (转)shell中test命令方法详解

    test命令用法.功能:检查文件和比较值 shell中test命令方法详解 原文:https://www.cnblogs.com/guanyf/p/7553940.html 1)判断表达式 if te ...

  8. 轻松学习Linux之Shell文件和目录属性详解

    轻松学习Linux之Shell文件和目录属性详解 轻松学习Linux之理解Sitcky 轻松学习Linux之理解umask 轻松学习Linux之理解SUID&SGUID 本系列多媒体教程已完成 ...

  9. shell编程之awk命令详解

    shell编程之awk命令详解 a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; out ...

随机推荐

  1. 安装和配置Apache服务器(上)

    首先,安装软件分安装版和压缩版,压缩版也就是我们现在所说的绿色安装包.安装板和压缩版的区别就是,安装板在安装的时候就已经自动给你配置好环境,压缩版安装之后还要自己配置环境.自己配置环境也是有好处的,知 ...

  2. 关于MVC开发时,无法找到area的问题记录

    解决方法: 检查area=admin 的dll是否生成,一般都是admin域生成dll导致

  3. 1036. [ZJOI2008]树的统计【树链剖分】

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. ...

  4. 1 TCP/IP通信

    重点参考长链接http://blog.csdn.net/fengyuzhengfan/article/details/38830115 http://blog.csdn.net/Jsagacity/a ...

  5. Python高级知识点总结

    一.可迭代对象.迭代器对象和生成器 像list, tuple等这些序列是可以使用for...in ...语句来进行遍历输出的.这是为什么呢?这就需要知道可迭代对象(Iterable).迭代器对象(It ...

  6. numpy库数组拼接np.concatenate的用法

    concatenate功能:数组拼接 函数定义:numpy.concatenate((a1, a2, ...), axis=0, out=None)

  7. RedHat Enterprise Linux 6.4使用Centos 6的yum源问题

    RedHat Enterprise Linux 6.4使用Centos 6的yum源问题 作为一名新手,学习Linux已经一个月了,其间遇到了不少问题,而今天笔者遇到的问题是 #yum install ...

  8. 静态工厂方法和实例工厂方法及普通的bean

    容纳你的bean  bean工厂:最简单的容器,提供了基础的依赖注入支持.创建各种类型的Bean.  应用上下文(ApplicationContext):建立在bean工厂基础之上,提供系统架构服务. ...

  9. Android github上的好的开源项目汇总

    转自:http://blog.csdn.net/ithomer/article/details/8882236 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上.基于 ...

  10. vxlan 简单理解 vs calico 网络模型

    1.vxlan(virtual Extensible LAN)虚拟可扩展局域网,是一种overlay的网络技术,使用MAC in UDP的方法进 行封装,共50字节的封装报文头. 2.VTEP为虚拟机 ...