Linux基础之sed流编辑器详解

之前介绍了三大文本编辑器的grep,这里介绍比grep功能更强的sed流编辑器


sed是什么?


sed是Stream EDitor的缩写,man中对sed的简介为

sed - stream editor for filtering and transforming text

它的主要功能是对文本的过滤与替换。




sed的工作原理


sed的工作过程:sed是一个流编辑器,所谓流编辑器是指sed每次只从文件或stdin中读入一行,将读入的行保存至模式空间然后根据指定的要求对其进行处理,并将处理后的结果输出至屏幕,接着读入下一行,整个文本的过程如流水线般被逐行处理后输出。


sed对内容的处理方式:sed不是在原文件中或原输入上直接进行处理的,它将读入的行放入缓存区,对缓存区里的内容进行处理,处理完毕后默认不会写入或覆盖源文件,而是直接输出到屏幕上。


它有两个内存缓冲区分别叫做:模式空间(pattern space)、保持空间也有称作暂存缓存区(holding space)。


一般情况下sed首先把第一行装入模式空间,进行处理后输出屏幕,然后第二行装入模式空间替换掉模式空间里原来的内容,再进行处理,依次循环,直至结束。


下面是我对sed工作流程的理解图。

wKioL1eq4ubyORJ9AAC2GrRqMkw154.jpg

1、sed每次将stdin中的内容中的一行读入模式空间

2、之后根据模式空间中的匹配条件进行匹配,符合条件进入下一阶段即普通编辑,不满足则默认至标准输出,结束

3、普通编辑之后分三个阶段,1)普通编辑之后选择性显示至STDOUT,结束;2)进入holding space进行高级编辑,编辑结束后选择性显示至模式空间,之后再次根据编辑命令重复2-3过程;3)若是出现多编辑命令则需要再返回模式空间根据编辑条件再次进行2-3步骤。

限于个人理解程度上述的理解免不了跟真实的工作流程有些出入,大家要抱着质疑的态度去看,我写的不一定都是对的,不过错的应该不至于很多。




sed语法

sed OPTIONS... <SCRIPT> [INPUTFILE...]

[SCRIPT]:可以理解为地址定界加编辑命令。

常用选项

         -n:不输出模式空间中的内容至屏幕;通俗点可以理解为它可以自动过滤掉模式空间中未匹配到的行,-n 要与命令编辑中的p合用(命令编辑见下文),用于显示模式空间中被匹配到的内容。

            suppress automatic printing of pattern space

         -n的具体应用见后面的sed编辑高级命令演示

         -e:多点编辑

            add the script to the commands to be executed

         -f:每行一个编辑命令

            add the contents of script-file to the commands to be executed

         -r:使用扩展表达式

            use extended regular expressions in the script.

         -i:直接编辑原文件

         edit files in place (makes backup if SUFFIX supplied)


SCRIPT

之前对这块很迷糊,因为info中sed显示语法有[]表示可加可不加,于是就在sed后直接加想要编辑的文本

于是就出现如下情况

[root@localhost test]# sed sed1
sed:-e 表达式 #1,字符 4:未终止的“s”命令

报错信息没找到终止的限制条件,所以上面的sed语法格式并不准确。

通过实验,sed可以不加[OPTION]但是[SCRIPT]则必须添加

SCRIPT分两部分地址定界(用于限定编辑文本的范围)、编辑命令(用于对匹配到的内容进行什么样的操作或编辑),前者可少后者必不可少,如果没有编辑的命令会发生如下错误

[root@localhost test]# sed '1' cat1
sed:-e 表达式 #1,字符 1:遗漏命令
[root@localhost test]# cat cat1
hi,everyone
now I will show how to use cat
[root@localhost test]# sed 'p' cat1
hi,everyone
hi,everyone
now I will show how to use cat
now I will show how to use cat

地址定界: 

        1、空地址:对全文处理

        2、单地址:

          #:指定行;

          /pattern/:被此模式所匹配到的每一行;

        3、地址范围:

         #,#:从#开始到#结束的所有行

         #,+#:从#开始向下至+#的行之间的所有行

         #,/pat1/ 从#开始至匹配到第一次出现/pat1/模式的行之间的所有行

         /pat1/,/pat2/:第一次匹配到/pat1/的行到第一次匹配到/pat2/的行之间的所有行

        4、步进:~

        1~2:所有奇数行          2~2:所有偶数行


编辑命令:若少了编辑命令会报错,编辑命令在SCRIPT中至少出现一次。


        d:删除模式空间中匹配到的内容       Delete pattern space

        a \text 在行后面插入文本“text”,支持使用\n实现多行插入

        Append text, which has each embedded newline  preceded  by  a  back slash.

        i \text 在行前面插入文本“text”,支持使用\n实现多行插入

        Insert  text,  which  has  each embedded newline preceded by a back slash.

        c \text 把匹配到的行替换为此处指定的文本“text”

       Replace the selected lines with text, which has each  embedded  new line preceded by a backslash.

        w filename 保存模式空间匹配的行至指定的文件中

              Write the current pattern space to filename.

        r filename 读取指定文件内容至当前文件被模式匹配到的行文件后合并

              Append text read from filename.

        =  : 为模式匹配到的行打印行号    Print the current line number.

       : 条件取反(它比较特殊,它必须跟其他编辑命令一起使用

      s/regexp/replacement/ : 查找替换,其分隔符可自行指定,常用有s@@@,s###

      它有一个特殊的用法s//x&/:表示将被查找的内容在其前面添加x内容

                        s//&x/:表示将被查找的内容在其后面添加x内容

                        &代表被查找的内容

[root@localhost test]# cat cat1
hi,everyone
now I will show how to use cat
[root@localhost test]# sed 's/e/&#/' cat1  
hi,e#veryone
now I will show how to use# cat
[root@localhost test]# sed 's/e/#&/' cat1 
hi,#everyone
now I will show how to us#e cat

                    p  :显示替换成功的行    

                    g  :全局替换

                    w  filename : 将替换成功的结果保存至指定文件中

      查找替换在sed中应用很广,下面很多例子都是以sed的替换功能实现的

        p  :显示当前模式空间中的内容    Print the current pattern space.


注:同时使用多个编辑命令,命令之间要用;隔开(!除外)

例子如下:

[root@localhost test]# sed 'p;=' cat1
hi,everyone
1
hi,everyone
now I will show how to use cat
2
now I will show how to use cat




实例演示

1、删除/etc/grub2.conf文件中所有以空白开头的行行首的空白字符

sed 's#^[[:space:]]\+##' /etc/grub2.cfg

这里##是将前面匹配到的内容删除的意思,上面文本内容太多,就不截取了。

2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#号及#后面的所有空白字符

sed 's@^#[[:space:]]\+@@' /etc/fstab
[root@localhost test]# cat /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Tue Jul 19 23:52:41 2016
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@localhost test]# sed 's@^#[[:space:]]\+@@' /etc/fstab
#
/etc/fstab
Created by anaconda on Tue Jul 19 23:52:41 2016
#
Accessible filesystems, by reference, are maintained under '/dev/disk'
See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0

3、在/etc/fstab每一行行首增加#号

cat /etc/fstab                           
#
# /etc/fstab
# Created by anaconda on Tue Jul 19 23:52:41 2016
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0
 sed 's@^@#&@' /etc/fstab
#
##
## /etc/fstab
## Created by anaconda on Tue Jul 19 23:52:41 2016
##
## Accessible filesystems, by reference, are maintained under '/dev/disk'
## See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
##
#/dev/mapper/centos-root /                       xfs     defaults        0 0
#UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot                   xfs     defaults        0 0
#/dev/mapper/centos-swap swap                    swap    defaults        0 0

4、处理/etc/fstab路径,使用sed命令取出其目录名和基名

目录名

[root@localhost test]# echo '/etc/fstab' | sed -r 's#(.*/)([^/]+/?)#\1#' 
/etc/

基名

[root@localhost test]# echo '/etc/fstab' | sed -r 's#(.*/)([^/]+/?)#\2#'
fstab




sed高级编辑命令:

    h:把模式空间中的内容覆盖至保持空间中;

    H:把模式空间中的内容追加至保持空间中;

    g:把保持空间中的内容覆盖至模式空间中;

    G:把保持空间中的内容追加至模式空间中;

    x:把模式空间中的内容与保持空间中的内容互换;

    n:覆盖读取匹配到的行的下一行至模式空间中;

    N:追加读取匹配到的行的下一行至模式空间中;

    d:删除模式空间中的行;

    D:删除多行模式空间中的所有行;

我知道看了上面这些高级命令一定很晕,下面通过5个例子来理一下使用sed高级编辑命令的思路


高级编辑命令实例演示:

1、    sed  -n  'n;p'  FILE:

''内意思:将读取到的行的下一行内容显示至模式空间

-n 'p':将模式空间中被匹配到的内容显示至屏幕

二者结合起来就是只显示偶数行。

[root@localhost test]# cat -n cat1
     1  hi,everyone
     2  now I will show how to use cat
[root@localhost test]# sed -n 'n;p' cat1
now I will show how to use cat


2    sed  '1!G;h;$!d'  FILE:

这个命令按'x;x;x'中的;号分割分为三部分:

1、1!G:除读取的第一行都进行G编辑

2、h:将模式空间中的内容覆盖至保持空间中

3、$!d:删除非最后一行的内容

命令解释完了,我想大家对此应该还是一头雾水,那么就具体说明这个命令的意思:

1)读取文本信息的1行内容至模式空间,由于是第一行所以模式空间中的1行不进行G操作,之后触发h,将模式空间中的1行放入保持空间中,再之后触发$!d,由于1行不是最后一行,所以将模式空间中的1行删除;

2)读取2行内容至模式空间,由于不是1行所以触发G操作,将保持空间中1行追加到2行后面,此时模式空间中的顺序内容为2行,1行,之后h命令将模式空间中内容覆盖至保持空间中,此时保持空间内容为2行,1行,因为2行不是最后一行,所以$!d删除模式空间中内容;

3)上述过程不断重复,直到最后一行时不进行d操作,此时模式空间中的第一行就是原文件的最后一行。

因此这个命令就是原文件内容反过来的排列。

[root@localhost test]# cat cat1
hi,everyone
now I will show how to use cat
[root@localhost test]# sed '1!G;h;$!d' cat1    
now I will show how to use cat
hi,everyone


3、    sed  '$!d'  FILE:

经过了上面两个命令的磨练,这个就显得简单了。

'$!d':不是最后一行则删除

意思是说模式空间中只保留文本的最后一行

[root@localhost test]# sed '$!d' cat1
now I will show how to use cat


4、    sed '/^$/d;G' FILE

'/^$/d':查找模式空间中的每行是否包含空白行,若包含则将其删除

G:将保持空间中的内容追加至模式空间中的每行后面

删除原有的所有空白行,而后为所有的非空白行后添加一个空白行;

二者结合在一起即:保证指定文件每一行后方有且只有一个空白行

[root@localhost test]# sed '/^$/d;G' cat1
hi,everyone

now I will show how to use cat


5、    sed  'n;d'  FILE:显示奇数行;

这个就很简单了,大家按照sed的工作原理及编辑命令n与d很容易就能明白其所表达的意思

[root@localhost test]# cat cat1
hi,everyone
now I will show how to use cat
[root@localhost test]# sed 'n;d' cat1
hi,everyone




学习sed的一些感受

    学习sed如果对于sed的编辑命令或高级命令很困惑,那么不妨试试照着我上面的sed工作流程图,一步一步的自己画图分析每一步所代表的意思。这既能加强自己对sed这个工具的了解也可有助于理清我们的使用思路。这是我在学习过程中觉得很有用的一种方法。

    sed这个工具它的精髓在于它的替换,替换的精髓在于精确匹配,而精确匹配又离不开正则表达式的,所以如果觉得自己对于替换很不擅长的话那么可以好好练习一下正则表达式。



sed是一个实用性很强的文本编辑工具,由于能力所限,也只能对sed进行下简要的介绍,大家若对其有进一步的兴趣可以查找更专业的书籍。

本文出自 “张帆-IT的奇幻漂流” 博客,请务必保留此出处http://chawan.blog.51cto.com/9179874/1836438

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

OpenVPN应用案例 - 2016-08-29 17:08:58

OpenVPN服务器的搭建: http://qicheng0211.blog.51cto.com/3958621/1575273 CentOS下OpenVPN客户端配置: http://qicheng0211.blog.51cto.com/3958621/1840055 应用一 、点对点安全通道 工作中可能会遇到这样的场景:由于业务需要,异地两台服务器需要安全的相互访问,除了拉专线,比较经济的方法就是通过公网建立加密隧道,openvpn是一个很好的选择。 服务端:内网IP192.168.20.220,vp
前段时间做了个项目,是关于父子域合并的,其实无非就是使用ADMT把域用户,计算机等从子域迁移到父域上,看似迁移用户很简单。But……生产环境啊,Exchange,TFS,Sharepoint,还有其余乱七八糟的东西,都使用了域账号,牵一发动全身的节奏,迁移账号出点儿问题相关用户就可以坐在那打酱油了,迁移前在他们生产环境中新建测试账号迁移,但是这种测试账号相对理想的环境,测试过程中很多问题不容易发现,很多问题是迁移了客户生产用户账号时出现了问题,但是于对于TFS一窍不通,sharepoint大多不懂的我来说
上一篇博客讲解了nginx相关的数据结构。 这一篇主要交接如何将自己的模块编译进nginx; 一种常用的简单方法: 1)首先把源代码文件全部放大一个目录下,然后在改目录中编写一个config用于通知Nginx如何编译本模块,这个文件名必须为config。 在configure脚本执行时加入参数--add-module=PATH(上面源码,config的保存目录) 执行正常安装流程是完成Nginx的编译工作。 ps:还有一种复杂方式,就是修改configure脚本执行后生成的obj/Makefile和obj

OpenLDAP 客户端部署 - 2016-08-29 17:08:32

有关服务端的安装请点击 一、账号登录系统流程讲解 当在客户端输入账号登录系统时,系统根据/etc/nsswitch.conf配置文件获取账号查找顺序,然后再根据PAM配置文件调用相关模块,对账号(/etc/passwd)及密码(/etc/shadow)进行查找并进行匹配。当本地匹配不成功时,会通过后端认证服务器(OpenLDAP服务器)进行验证。 二、配置文件功能介绍 下面介绍几个配置文件再后面我们会进行修改,我这里简单介绍一下。 /etc/nsswitch.conf 该文件主要用于名称转换服务,用于系统
1. root下进入其他用户主目录 cd ~USERNAME 2. touch的另外的一种作用 常用的是touch创建一个不存在的文件 而touch一个存在的文件时候,touch会修改文件的三个时间(使用stat可以查看),其中access表示最后一个访问时间,modify表示最后一次修改文件的时间,change表示最后修改文件属性的时间 3. file查看文件类型 镜像文件(iso)的文件类型为iso9660 4./etc/passwd中各字段对应解释 1 用户名:2密码:3uid:4gid:5备注:6
谁说Lync Server 前端不可以使用Windows网络负载平衡实现高可用的?(仅限测试环境) 本章内容有: 1.两台Lync Server安装Windows功能---网络负载平衡 2.配置网络负载平衡 3.DNS记录修改 4.测试故障切换(模拟两种故障,网络故障和服务故障) 5.开始的时候别忘了上一章中的提示,将两台前端Server都进行重启 = = 安装网络负载平衡 两台服务器都需要进行安装 = = 配置网络负载平衡 1)新建群集 2)将LyncFE01先添加到群集中 3)群集IP自己随便填写 4

深入剖析linux磁盘管理 - 2016-08-29 17:08:26

一、linux中常见的磁盘: 无论什么操作系统,归根还是要落实与磁盘上的,对于磁盘的管理也是linux管理必备的一项技能。在linux中“一切皆文件”的思想贯彻整个linux的学习中,包括像是磁盘等的硬件也是在linux的/dev/目录下类似于文件形式的存放,常见的SATA口USB优盘或是SCSI口的硬盘在linux中是以/dev/sd[a-p]开头的文件,早期的IDE硬盘现在已经很少见了,这种硬盘在linux中是以/dev/hd[a-d],CDROM是以/dev/cdrom开头的文件,磁带机/dev/s

linux实战题 - 2016-08-29 17:08:10

在配置Apache时,执行了./configure --prefix=/application/apache2.2.17来编译Apache,在make install完成后,需要用户的访问路径更加简单 ,需要给/application/apache2.2.17目录做一个软链接/application/apache,是得内部人员可以通过/application/apache就可以访问到Apache的安装目录/application/apache2.2.17下的内容 ,请给出实现命令。(安装时有版本号,后面使
一 VNC简介 VNC 是在基于Linux 操作系统的免费的开源软件,远程控制能力强大,高效实用,其性能可以和 Windows 和 MAC 中的任何远程控制软件媲美。 在 Linux 中,VNC 包括以下四个命令:vncserver,vncviewer,vncpasswd,和 vncconnect。大多数情况下用户只需要其中的两个命令:vncserver 和 vncviewer VNC基本上是由两部分组成:一部分是 客户端的应用程序(vncviewer) ;另外一部分是 服务器端的应用程序(vncserv
目标: 在xuegod63.cn服务器上,使用网站模版UCenter_1.5.0_SC_UTF8.zip和UCenter_Home_2.0_SC_UTF8.zip为公司搭建一个类似人人网的网站。在windows上,使用访问uc.duwers63.cn可以访问UCenter;使用www.duwers63.cn可以访问UCenter_Home。 安装 yum-yinstallhttpdmysql-servermysqlphpphp-mysql 软件包解释: httpd#web网站服务器 mysql-serve