• 流编辑器Sed


    Sed简介

    Sed是一款流编辑工具,用来对文本进行过滤与替换操作,特别是当你想要对几十个配置文件做统一修改时,你会感受到Sed的魅力!Sed通过一次仅读取一行内容来对某些指令进行处理后输出,所以Sed更适合于处理大数据文件。首先,Sed通过文件或管道读取文件内容,但Sed默认并不直接修改源文件,而是将读入的内容复制到缓冲区中,我们称之为模式空间(pattern space),所有的指令操作都是在模式空间中进行的,然后Sed根据相应的指令对模式空间中的内容进行处理并输出结果,默认输出至标准输出(即屏幕上)。Sed工作流程如下图所示:

    Sed基本语法格式

    Sed从文件中读取数据,如果没有输入文件,则默认对标准输入进程数据进行处理,脚本指令是第一个非“-”开头的参数,具体语法格式如下。

    用法:sed[选项]...{脚本指令} [输入文件]...
    选项:--version          显示sed版本
       -h或--help          显示帮助文档
       -n或--quiet或--silent  静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,该选项可以屏蔽自动打印

       -e script       允许多个脚本指令被执行
       -f script-file      从文件中读取脚本指令,对编写自动脚本程序很实用
       -i或-in-place     慎用,该选项将直接修改源文件
       -l N          该选项指定l指令可以输出的行长度,l指令为输出非打印字符
       --posix       禁用GNU sed扩展功能
       -r           在脚本指令中使用扩展正则表达式
       -s或--separate    默认情况下,sed将把输入的多个文件名作为一个长的连续的输入流。而GNU sed则允许把它们当作单独的文件
       -u或-unbuffered  最低限度的缓存输入与输出

    Sed 入门范例

    1. 基本格式范例

    Sed 通过特定的脚本指令对文件进行处理,这里就简单介绍几个脚本指令操作作为Sed程序的范例。a,append表示追加指令;i,insert表示插入指令;d,delete表示删除指令;s,substitution表示替换指令。sed脚本指令的基本格式是:[地址]命令(有些命令仅可以对一行操作,有些可以对多行操作),命令也可以用花括号进行组合,使命令序列可以作用于同一个地址。

    address {
    command1
    command2
    command3
    }

    下面的test.txt为操作样本源文件(注意有若干空白行),介绍Sed的用法。

    [root@192 ~]# cat test.txt
    DEVICE=ens33
    BOOTPROTO=static
    IPADDR=192.168.0.1
    NETMASK=255.255.255.0
    GATEWAY=192.168.0.254

    ONBOOT=yes

    [root@192 ~]# sed '2a TYPE=Ethernet' test.txt     # 第二行后追加TYPE=Ethernet

    [root@192 ~]# sed '3i TYPE=Ethernet' test.txt      # 第三行前追加TYPE=Ethernet 

    [root@192 ~]# sed 's/yes/no/g' test.txt                # 将样本文件中的所有yes替换为no 

    [root@192 ~]# sed '3,4d' test.txt                           # 删除第3,4行的内容

    [root@192 ~]# sed -e '3,4d' test.txt                       # 删除第3,4行的内容

    注意:这里 sed -e 和 sed 是一样的!同时也要注意的是,sed 后面接的动作,请务必以 '' 两个单引号括住!

    以上大多数操作指令都依据行号定位操作对象(地址),如:2a即第二行后追加。

    实际工作中,可能大多数情况你并不确定你要操作对象(地址)的行号,这时更多的会使用正则表达式确定操作对象(地址)。下面是使用正则表达式定位操作行的示例:

    匹配到包含ONBOOT的行,并在其后添加TYPE=Ethernet:

    [root@192 ~]# sed '/ONBOOT/a TYPE=Ethernet' test.txt

    匹配以GATEWAY开始的行,并删除该行:

    [root@192 ~]# sed '/^GATEWAY/d' test.txt

    另外,我们的操作指令可以写入到脚本文件中,并通过sed的-f选项读取,脚本文件中的注释行是以#开始的行,如果#后面的字符为n,则屏蔽Sed程序的自动输出功能,等同于命令选项-n。

    创建一个sed脚本,内容如下:

    [root@192 ~]# cat sed.sh      # 脚本内容为匹配到空白行后,删除该行
    # This is a test sed command
    /^$/d

    [root@192 ~]# sed -f sed.sh test.txt      # 对test.txt文件执行sed.sh脚本指令

    而当你需要执行多个指令时,可以使用以下三种方法:

    [root@192 ~]# sed 's/yes/no/; s/static/dhcp/' test.txt       # 使用分号隔开指令

    [root@192 ~]# sed -e 's/yes/no/' -e 's/static/dhcp/' test.txt      # 使用-e选项

    [root@192 ~]# sed '            # 利用分行
    > s/yes/no/
    > s/static/dhcp/' test.txt

    然而在命令行上输入过长的指令是愚蠢的,这时需要使用-f选项指定sed 脚本文件,在脚本文件中可以包含多行指令,而且也便于修改。

    2. 操作地址匹配范例

    通过以上范例不难发现,我们编写的脚本指令需要指定一个地址来决定操作范围,如果不指定,则默认对文件的所有行进行操作。如:sed 'd' test.txt将删除test.txt的所有行,而'2d'则仅删除第二行。Sed为我们提供了以下这些方式来确定需要操作地址的范围。

    number       指定输入文件的唯一行号

    first~step      指定以first开始,并指定操作步长为step,如1、2指定第一行、第三行、第五行……为操作地址。2~5指定第二行开始,每5行匹配一次操作地址

    [root@192 ~]# sed -n '1~2p' test.txt  # 打印文件的奇数行

    $          匹配文件的最后一行

    /regexp/       //中间包含的是正则表达式,通过正则表达式匹配操作地址。如果//中正则表达式为空,匹配最近一次正则表达式的匹配地址

    cregexpc      c与c之间匹配扩展正则表达式,c字符可以使用任意字符替代

    addr1,addr2    匹配从操作地址1到操作地址2的所有行

    [root@192 ~]# sed '2,8d' test.txt  # 删除2~8之间的所有行

    addr1,+N     匹配地址1以及后面的N行内容

    Sed指令与脚本

    1. Sed常用指令汇总

    下表给出了常用的sed脚本指令的说明,下面分别看看每个指令的详细用法。

    指令 功能 指令 功能
    s 替换 d 删除
    a 追加 i 插入
    c 更改 l 打印(显示非打印字符)
    y 按字符转换 L 打印(不显示非打印字符)
    p 打印 r 读入文件内容
    w 保存至文件 q 退出

    2. Sed脚本指令范例

    范例1

    范例1所使用的样本文件为(注意有空白行):

    [root@192 ~]# cat test.txt
    DEVICE=ens33
    ONBOOT=yes
    BOOTPROTO=static

    IPADDR=192.168.0.1
    NETMASK=255.255.255.0

    GATEWAY=192.168.0.254

    范例1:删除文件中空白行

    编写sed脚本为:

    [root@192 ~]# cat sed.sh
    /.*/{
    /^$/d
    }

    执行sed程序的结果如下:

    [root@192 ~]# sed -f sed.sh test.txt
    DEVICE=ens33
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=192.168.0.1
    NETMASK=255.255.255.0
    GATEWAY=192.168.0.254

    范例2~范例5所使用的样本文件为:

    [root@192 ~]# cat test.txt
    DEVICE=ens33
    ONBOOT=yes
    BOOTPROTO=static
    NETMASK=255.255.255.0
    GATEWAY=192.168.0.254

    范例2:在static行后添加一行,内容为IPADDR=192.168.0.1

    [root@192 ~]# sed '/static/a IPADDR=192.168.0.1' test.txt

    范例3:在匹配NETMASK的行前插入内容IPADDR=192.168.0.1

    [root@192 ~]# sed '/NETMASK/i IPADDR=192.168.0.1' test.txt

    范例4:将包含ONBOOT行的内容更改为ONBOOT=no

    [root@192 ~]# sed '/ONBOOT/c ONBOOT=no' test.txt

    范例5:列印(l)显示模式空间中的内容,显示非打印字符,一般与-n一起使用,否则会输出两次

    [root@192 ~]# sed -n '1,2l' test.txt    # 在sed脚本文件中,需要#n屏蔽自动输出

    结果如下:

    DEVICE=ens33$
    ONBOOT=yes$

    范例6:显示第一、二行的内容

    打印(p):作用类似于l(列印),但不显示非显示字符,一般与-n配合使用

    [root@192 ~]# sed -n '1,2p' test.txt

    结果如下:
    DEVICE=ens33
    ONBOOT=yes

    范例7:显示test.txt内容的前两行内容后退出sed指令

    [root@192 ~]# sed '2q' test.txt

    范例8:直接修改文件内容(危险动作)

    注意:sed -i 可以直接修改文件的内容,不必使用管道命令或重定向! 不过,由于这个动作会直接修改到原始的文件,所以请你千万不要随便拿系统配置来测试!

     [root@192 ~]# sed -i 's/yes/no/' test.txt

    范例9:在test.txt最后一行加入# This is a test!

    [root@192 ~]# sed -i '$a # This is a test!' test.txt

    范例10:批量替换指定目录下所有文件的指定内容

    [root@192 ~]# sed -i 's/https/http/g' `grep https -rl demo`

    功能:用来替换当前demo目录下文件及子文件中所有文件中的https为http

    说明:

    -i 表示inplace edit,就地修改文件

    -r 表示搜索子目录

    -l 表示输出匹配的文件名

     

    参考自,丁明一    编著    《Linux运维之道》

  • 相关阅读:
    windows快捷键十八式(win10)
    解决滚动条突然出现导致的页面错位问题
    用命令行撤销工作区的所有更改(修改文件&&新增文件)
    用animation的steps属性制作帧动画
    配置Gitlab pages和Gitlab CI
    zookeeper中的分布式一致性协议
    kafka消息的处理机制(五)
    Paxos算法原理
    kafka同步异步消费和消息的偏移量(四)
    kafka客户端和服务端开发(三)
  • 原文地址:https://www.cnblogs.com/opsprobe/p/11622073.html
Copyright © 2020-2023  润新知