一、流编辑器 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. time模块案例演示

    案例01: 2008年8月8日20:08:08 往后88,888,888秒是哪天?星期几? 日期->时间戳(浮点数)->可以做数学运算 演示: import time # 构造日期的元组, ...

  2. Spring Boot 验证表单

    在实际工作中,得到数据后的第一步就是验证数据的正确性,如果存在录入上的问题,一般会通过注解校验,发现错误后返回给用户,但是对于逻辑上的错误,很难使用注解方式进行验证了,这个使用可以使用Spring所提 ...

  3. SDN期末作业-通过SDN的应用实现负载均衡

    负载均衡程序 1.程序链接:https://github.com/424baopu/software/tree/master/LoadBalance 2.场景 topo: 场景描述: 服务器host ...

  4. wx.aui.AuiManager部分/布局翻译

    wx.aui.AuiManager wx.aui.AuiManager 是AUI框架类中的主要类 wx.aui.AuiManager管理于指定的wx.Frame相关联的窗口,通过使用窗口的wx.aui ...

  5. 方法(method)和函数(function)的区别

    函数是一段代码,通过名字来进行调用.它能将一些数据(参数)传递进去进行处理,然后返回一些数据(返回值),也可以没有返回值. 所有传递给函数的数据都是显式传递的. 方法也是一段代码,通过一个与对象相关联 ...

  6. JSSDK图像接口多张图片上传下载并将图片流写入本地

    <span style="font-size: 14px;"><!DOCTYPE html> <html lang="en"> ...

  7. str操作方法

    s = 'dsj,fhk,je,f' # s1 = s.split(',') # print(s1) s = 'aleX leNb' s1 = s.strip() print(s1) s2 = s[2 ...

  8. redhat7.4 使用centos yum源

    新安装了redhat7.4安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription Ma ...

  9. Ubuntu16.04之开发环境构建

    Ubuntu软件安装相对于centos而言,那真的是要愉快的多啊! 以下安装步骤,本人在公司的测试环境和开发环境以及之前个人虚拟机的测试或生产环境都测验过,基本没有问题,只要按照步骤来,即可马到成功! ...

  10. 客户端本地存储的比较及使用window.name数据传输

    一:cookie: 1. 什么是cookie? Cookie是在客户端用于存储会话信息的,用户请求页面在web服务器与浏览器之间传递.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cooki ...