文本处理三剑客之sed

文本处理三剑客之sed


  • sed概述

  • sed使用示例

  • sed的高级应用


sed概述

sed, 作为文本三剑客之一,其定位就是一个编辑器, 而且sed是一个流式编辑器(stream editor),其主要功能是过滤和转换文本。

sed - stream editor for filtering and transforming text

作为一个强大的文本处理功能,sed 自然能够配合正则表达式,另外,所谓流编辑器,sed 是逐行地读取文本,在文本行中应用指定的命令,且默认输出到stdout; sed 拥有两个缓冲区,活跃模式空间(active pattern space)与辅助保持空间(auxiliary hold space), 简称为模式空间与保持空间,且这两个空间默认都为空。

`sed' maintains two data buffers: the active _pattern_ space, 
and theauxiliary _hold_ space. Both are initially empty.

sed的基本应用只用到模式空间就够了,sed的高级应用需要模式空间与保持空间的想到配合。在sed

的基本应用中,sed会把当前处理的行存储在一个临时缓冲区,即模式空间;然后sed会在模式空间中处理文本,并且传送到标准输出,再接着处理下一行,如
此循环往复,直至文件末尾,这就是sed的基本工作原理。由此可风,sed在默认情况下是不修改原文件的;在sed的高级应用中,多了一个保持空间,保持
空间是与模式空间进行交互的,且以模式空间为主,保持空间为辅,sed匹配的内容最终都得经由模式空间传输至stdout.

常用参数

  1. -n: –quiet, –silent, 静默模式,不输出模式空间内容的自动打印

  2. -e: –expression=script, 多点编辑,类似于管道

  3. -f: –file=script-file, 从指定文件中读取sed脚本

  4. -r: 支持使用扩展正则表达式

  5. -i: 原处编辑,-i.bak可同时作备份

sed地址定界

所谓sed的地址定界,就是我们对要处理的文本给出一个范围,然后让sed只针对此范围去做相应的处理。

  1. 不给地址,默认全文处理

  2. 单地址:

    #:指定的行
     /pattern/:被此模式所能匹配到的每一行
  3. 地址范围:

    #,#:从多少行到多少行
     #,+#:从第#行起至第#行+#行结束(相对地址)
     #,/part/: 从第#行开始,到第一次匹配到/part/模式结束
     /part1/,/part2/: 从第一次匹配到/part1/开始,到最后一次匹配到/part2/结束
  4. 步进: ~

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

sed编辑命令

  1. d: 删除模式空间匹配到的行

  2. p: 显示模式空间中的内容

  3. a \test: 在行后面追加文本,\可用空格替代;支持使用\n 实现多行追加

  4. i \test: 在行前面插入文本,\可用空格替代;支持使用\n 实现多行插入

  5. c \test: 替换为单选或多行文本,\可用空格替代

  6. w /PATH/TO/SOMEFILE: 另存为模式匹配的行到指定文件

  7. r /PATH/TO/SOMEFILE: 读取指定文件的文本至模式空间匹配到的行后

  8. =: 为模式空间的行打印行号

  9. !: 模式空间匹配的行作反处理

  10. s///: 查找替换,支持使用其它分隔符,如s@@@, s###

替换标记:
            g: 行内全局替换
            p: 显示替换成功的行
            w /PATH/TO/SOMEFILE:将替换成功的行保存至指定的文件中


sed使用示例

创建一个测试文件:

[root@centos7 ~#]cat f1
1
2
3
4
5
  1. 删除f1中的空格并写入原文件

[root@centos7 ~#]sed -i '/^$/d' f1

wKiom1erEDvSleAdAABC4VPEYmQ943.png

  1. 删除1-3行

[root@centos7 ~#]sed '1,3d' f1
4
5
[root@centos7 ~#]
  1. 打印出第2行,并说明默认打印模式空间的意义

[root@centos7 ~#]sed -n '2p' f1   # 只打印出了第2行
2
[root@centos7 ~#][root@centos7 ~#]sed '2p' f1
1
2                               # sed 默认显示出模式空间中的2
2                               # sed 匹配到第2行并打印出
3
4
5
  1. 给第2行后加入‘liansir’字样,在第3行前加入‘xiaolei'字样,替换第4行为’lvxing'

[root@centos7 ~#]nl f1 |sed -e '2a \liansir' -e '3i \xiaolei' -e '4c \lvxing' 
     1  1           # 命令n: nl - number lines of files
     2  2
liansir
xiaolei     
     3  3
lvxing     
     5  5
[root@centos7 ~#]
  1. 给f1加入空格后并显示空格行号

[root@centos7 ~#]sed -n '/^$/=' f1

wKioL1erEYfhxMeiAAAxw1iZk_A483.png

  1. 给数字2后加'liansir'字样,给数字3前加'xiaolei'字样

[root@centos7 ~#]sed -e 's/2/&liansir/' -e 's/3/xiaolei&/' f1

wKioL1erJifjoTt9AAAyaxK3ZTI975.png

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

[root@centos7 ~#]sed -r 's/^[[:space:]]+//' /etc/grub2.cfg   # 以“替换”的方式实现了“删除”,-r 表示使用扩展正则表达式

wKioL1erJonjH9eRAAB3iSDcYtk073.png

wKiom1erJpyx_RNjAAAxw1iZk_A118.png

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

[root@centos7 ~#]sed -r 's/^#[[:space:]]*//' /etc/fstab

wKiom1erJqySxaeQAACjBTSSyu4251.png

wKioL1erJseiBuAgAACjjU_TG1s241.png

  1. 在/root/install.log每一行行首增加#号

[root@centos6 ~#]sed 's/^/#/' /root/install.log
或[root@centos6 ~#]sed -r 's/(.*)/#\1/' /root/install.log  # 后向引用,注意使用扩展正则表达式
或[root@centos6 ~#]sed -r 's/(.*)/#&/' /root/install.log

wKioL1erJuaA8zJNAACRixUhHXU596.png

  1. 处理/etc/fstab路径,使用sed命令取出其目录名和基名 (此题有料,众多解法,有兴趣者探索之)

取基名:下面命令的主要思路是不管前面是什么,只锚定最后一个单词的开头

[root@centos6 ~#]echo '/etc/fstab' |sed -r 's/(.*)\/<//'  # 注意转义
/etc/fstab
[root@centos6 ~#]
[root@centos6 ~#]echo '/etc/fstab' |sed -r 's@(.*)/<@@'  # 不想转义可直接换分隔符
/etc/fstab
[root@centos6 ~#]echo '/etc/fstab/' |sed -r 's@(.*)/<@@' # 当基名为一个目录时照样适用
/etc/fstab/
[root@centos6 ~#]

取目录名:着眼点还是在后面的基名上,即删除了基名

[root@centos6 ~#]echo '/etc/fstab' |sed -r 's@[^/]+/?$@@'
/etc/
[root@centos6 ~#]echo '/etc/' |sed -r 's@[^/]+/?$@@'     
/
[root@centos6 ~#]

取目录名与基名的完美解法

[root@centos6 ~#]echo /etc/fstab |sed -r 's@(.*/)([^/]+/?)$@\1@'  # 取目录名
/etc/
[root@centos6 ~#]echo /etc/fstab |sed -r 's@(.*/)([^/]+/?)$@\2@'  # 取基名
fstab
[root@centos6 ~#]

完美之外:

1. 涉及到/ 时则换分隔符,避免转义,如@
2. 将目录名与基名以分组的形式分别表示出来,表达了一个完整的路径
3. 分别后向引用则可取得目录名或基名,属于通用解法
  1. 利用sed 取出ifconfig命令中本机的IPv4地址 # 先打印出本机IP所在行,然后"掐头去尾"。

[root@centos7 ~#]ifconfig |sed -n '2p' |sed -e 's/.*inet//' -e 's/net.*//'
 10.1.253.100  
[root@centos7 ~#]
  1. 统计centos安装光盘中Package目录下的所有rpm文件的以.分隔倒数第二个字段的重复次数

[root@centos6 /media/CentOS_6.8_Final/Packages#]ls |sed -r 's@.*\.(.*)\.rpm$@\1@' |sort |uniq -c
      4 i686    
      919 noarch      
      1 TRANS.TBL   
      2283 x86_64
[root@centos6 /media/CentOS_6.8_Final/Packages#]
# 注意\.是转义.

至此,我们再来了解下sed的高级应用!

sed高级编辑命令:

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

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

  3. g: 从保持空间读取数据覆盖至模式空间中

  4. G: 从保持空间读取数据追加至模式空间中

  5. x: 把模式空间中的内容与保持空间的内容进行互换

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

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

  8. d: 删除模式空间中的行

  9. D: 删除当前模式空间开端至\n的内容(不再传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed.

h H    Copy/append pattern space to hold space.
g G    Copy/append hold space to pattern space.
x      Exchange the contents of the hold and pattern spaces.
n N    Read/append the next line of input into the pattern space.
d      Delete pattern space.  Start next cycle.

可见,模式空间与保持空间的交互命令有:h, H, g, G, x.其流向关系可用下图表示:

wKioL1erJ2yjr5zhAAAhKP-QJ_c512.png

sed高级应用示例

创建一个测试文件:

[root@centos7 ~#]echo {1..5} |tr ' ' '\n' >f1
[root@centos7 ~#]cat f1
1
2
3
4
5
[root@centos7 ~#]
  1. 输出偶数行与奇数行:

普通用法:
[root@centos7 ~#]sed -n '1~2p' f1
1
3
5
[root@centos7 ~#]sed -n '2~2p' f1
2
4
[root@centos7 ~#]
高级用法:
[root@centos7 ~#]sed 'n;d' f1   
1
3
5
[root@centos7 ~#]sed -n 'n;p' f1
2
4
[root@centos7 ~#]

高级用法解析:

~#]sed 'n;d' f1
    首先,sed读入第一行的1到模式空间,n动作匹配到第二行中的2并覆盖掉
    模式空间中的1,此时模式空间中仅有2,又因为d动作被删除了,模式空间全
    空了!那怎么又输出1了呢?这是因为sed 没有使用-n选项,故1在被2覆盖之
    前已被sed默认输出,而2在模式空间却被d给干掉了,故而屏幕上输出了1。
    然后sed双读入第三行中的3,被n匹配至其下一行中的4并读入模式空间,但
    在4覆盖3之前sed已默认打印出3,而4却“胎死腹中”,故屏幕双留下了3.

~#]sed -n 'n;p' f1 
    首先,sed 读入第一行的1到模式空间,因为n动作,又匹配到第二行中的2,
    并把2读入模式空间覆盖掉之前的1,模式空间中的内容输入至stdout而得到2.
    然后,sed读入第三行中的3到模式空间,因为n动作,匹配到其下一行中的4,
    并把4读入模式空间并覆盖掉之前的3并p至stdout.
  1. 倒序输出:

[root@centos7 ~#]sed '1!G;h;$!d' f1
5
4
3
2
1
[root@centos7 ~#]

高级用法解析

~#]sed '1!G;h;$!d' f1
    这个sed命令,整体被分别;分隔为三段,我们认为他有三个动作:
    1!G;  如果不是第1行,则把保持空间中的内容追加至模式空间(保持空间默认为空)    
    h;    把模式空间中的内容覆盖至保持空间
    $!d   如果不是最后一行则删除

结合sed流编辑器的特点,逐行读入,意味每读入一行便会执行上面的三个动作;
每一行:
1. sed读入第一行中的1到模式空间,由于不符合'1!'这个条件,则跳过G执行h;
2. h 把模式空间中的1覆盖至保持空间;(此时模式空间中为1,保持空间中为1)
3. 1不是最后一行,符合条件'$!',删除(此时模式空间为空,保持空间都为1)
第二行:
1. sed读入第二中的2至模式空间,符合'1!'这个条件,从而执行G动作,G把
保持空间中的1追加至模式空间;
于是,此时模式空间中的内容为:
2
1
但保持空间是1
2. h 把模式空间中的内容覆盖至保持空间
3. 执行 $!d(模式空间为空)

依次类推,当执行完第四步时,情况是这样的:模式空间为空,保持空间的内容为:
4
3
2
1
第五步:
1. sed读入第五行中的内容5至模式空间,符合'1!'这个条件,执行G动作,把
保持空间中的内容追加到模式空间
2. h 把模式空间中的内容覆盖至保持空间
3. 第五行是最后一行,不符合'$!',跳过$!d于是,屏幕上显示:
5
4
3
2
1

一个sed的高级命令,应得大费如此篇幅,目的就是更为深入地理解sed这个流编辑器,逐行处理文本,有两个模式空间,一主一辅。看下图(图片来自网友),就更能清楚地理解sed的工作原理了。

wKioL1erKAbClxluAAB_8W01-iY715.png

此图仅供参考!

  1. 一锅上了先

[root@centos7 ~#]sed '$!N;$!D' f1
4
5
[root@centos7 ~#]
[root@centos7 ~#]sed '$!d' f1  # 不是最后一行则删除,意味着最后一行保留输出
5
[root@centos7 ~#]
[root@centos7 ~#]sed 'G' f1   # 保留空间默认为空
1

2

3

4

5
[root@centos7 ~#]

[root@centos7 ~#]sed 'g' f1





[root@centos7 ~#]sed 'g' f1 |wc -l  # 可见输出了5个空格
5
[root@centos7 ~#]
[root@centos7 ~#]sed '/^$/d;G' f1
1
2
3
4
5
[root@centos7 ~#]
[root@centos7 ~#]sed -n '1!G;h;$p' f1  # 看与高级应用分析与区别
5
4
3
2
1
[root@centos7 ~#]
4. 交换模式空间与保持空间的内容
[root@centos7 ~#]sed 'x' f1  # 模式空间中最后交换了一行被保留空间中第一个空白替换了

1
2
3
4
[root@centos7 ~#]

sed 的功能如此强大,掌握也非一日之功,sed可以帮助我们自动编辑一个或多个文件,简化对文件的反复操作,编写程序转换等。

原创文章,作者:Liansir,如若转载,请注明出处:http://www.178linux.com/33184

(0)
LiansirLiansir
上一篇 2016-08-12
下一篇 2016-08-12

相关推荐

  • 网络理论基础

    一、网络概述   1、什么是网络     网络就是通过有线或无线技术将各种硬件设备连接起来进行数据传输的一种方式。   2、网络的分类     根据距离范围可以将网络划分为局域网和广域网。       局域网:传输距离较近,传输速率快。     &n…

    Linux干货 2016-01-11
  • centos 7 之nmcli命令

    1、nmcli命令的作用 nmcli : command‐line tool for controlling NetworkManager     NetworkManager:动态管理和监控网络设置的守护进程。用户和脚本都可使用命令行工具 nmcl…

    Linux干货 2016-09-10
  • Linux基础之安全加密及CA、证书实战应用

    一、建立私有CA并让客户端申请请求,需要两台虚拟机完成 1、建立私有CA,生成私钥 2、CA公司给自己,生成自签证书 3、为CA提供所需要的目录及文件(如果事先存在,此步骤可以跳过) 二、CA公司已建立,需要一台客户机配合CA签署证书 1、客户端用到证书,因此生成私钥 2、客户端生成证书签署请求 3、将请求通过可靠方式发送给CA主机,这里作为测试,因此使用s…

    Linux干货 2016-10-04
  • 两张盘合并做yum源

    第一步 先把两张光盘都连接到系统中 连接上iso文件后重启电脑 这时桌面会显示已将连接上的iso文件   然后创建两个文件夹分别挂载这两个光盘   mkdir centos6.9-{1,2} 创建两个文件夹 df 查看系统硬盘   然后把两个光盘分别挂载到文件中 mount -o ro,loop /dev/sr0 centos6…

    2017-07-12
  • RAID 0 软件实现

    RAID 0 软件实现        RAID 0又称为Stripe或Striping,它代表了所有RAID级别中最高的存储性能。RAID 0提高存储性能的原理是把连续的数据分散到多个磁盘上存取,这样,系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行…

    Linux干货 2017-05-02
  • 18-系统启动故障修复-实践

    说明:重启时可以选择性在vmlinuz所在行末尾添加 selinux=0;或者直接编辑/etc/selinus/config文件,更改 SELINUX=disabled 关闭SELINUX。可以避免打标签,节省启动时间 以下操作都需要进入bootloader引导加载项修改内核启动参数,在vmlinuz所在行末尾添加一个启动选项 如何进入bootloader引…

    2017-04-02