zoukankan      html  css  js  c++  java
  • 09 sed

    三剑客之sed命令

    一 sed介绍

    ​ sed全称(stream editor)流式编辑器,Sed主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等,工作流程如下

    sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在
    临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完
    成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有
    改变,除非你使用重定向存储输出,或者使用sed -i选项
    -i选项就是将本该输出到屏幕上的内容输出/流入文件中
    

    ​ sed命令格式如下

    sed [options] 'command' file(s)
    sed [options] -f scriptfile file(s)
    
    # 注:
    sed和grep不一样,不管是否找到指定的模式,它的退出状态都是0
    只有当命令存在语法错误时,sed的退出状态才不是0
    

    二 sed选项与基本用法示例

    2.1 sed选项

    选项			   功能
    -e				允许多项编辑
    -n				取消默认的输出(模式空间的内容输出)
    -i				inplace,就地编辑
    -r				支持扩展元字符
    -f				指定sed脚本文件名
    
    示例
    # sed -r '' /etc/passwd
    # sed -r 'p' /etc/passwd
    # sed -r -n 'p' /etc/passwd	
    
    
    文件的一行行内容相当与水流,连续两个-e就是设置了两道关卡
    [root@aliyun ~]# sed '' test.txt 
    1111111
    2222222egon
    333333egon
    444444egon
    555555eon
    [root@aliyun ~]# sed -e '3d' -e '1d' test.txt  
    2222222egon
    444444egon
    555555eon
    [root@aliyun ~]# sed -rn -e '1,3d' -e 'p' test.txt
    444444egon
    555555eon
    [root@aliyun ~]# 
    
    也可以将多道关卡写入一个文件中
    [root@aliyun ~]# cat sed.txt 
    1,3d
    p
    [root@aliyun ~]# sed -rn -f sed.txt test.txt
    444444egon
    555555eon
    [root@aliyun ~]# 
    

    2.2 sed命令组成

    命令由”地址+命令“两部分组成,命令如p、d,更多详解第三章节,本节我们主要介绍地址

    地址用于决定对流入模式空间的哪些行进行编辑,如果没有指定地址,sed将处理流入模式空间的所有行。

    地址可以是

    • 1、数字

      sed -n 'p' /etc/passwd	
      sed -n '1,3p' /etc/passwd	
      sed '1,47d' /etc/passwd
      
    • 2、正则表达式

      与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式是
      括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。
      
      # 使用基本元字符集	
      ^, $, ., *, [], [^], < >,(),{}
      
      # 使用扩展元字符集	
      ?, +, { }, |, ( )
      
      # 使用扩展元字符的方式:
      转义,如+
      -r参数,如sed -r
      
      [root@aliyun ~]# cat test.txt 
      1111111
      2222222egon
      333333egon
      444444egon
      555555eon
      [root@aliyun ~]# sed -rn '/egon/p' test.txt 
      2222222egon
      333333egon
      444444egon
      [root@aliyun ~]# 
      
    • 3、数字+正则表达式

      [root@aliyun ~]# cat test.txt 
      1111111
      2222222egon
      333333egon
      444444egon
      555555eon
      [root@aliyun ~]# sed -rn '1,/egon/p' test.txt 
      1111111
      2222222egon
      [root@aliyun ~]# 
      
      解释:
      # "1,8p"代表打印1到8行,"1,/egon/p"则代表取从第1行到首次匹配到/egon/的行
      

    2.3 cregexpc

    地址可以是正则表达式,而正则表达式需要放置在c与c中间,其中c可以是任意字符,但必须要加转义

    [root@aliyun ~]# cat test.txt 
    1111111
    2222222egon
    333333egon
    444444egon
    555555eon
    [root@aliyun ~]# sed -rn '#egon#p' test.txt 
    [root@aliyun ~]# sed -rn '#egon#p' test.txt 
    2222222egon
    333333egon
    444444egon
    [root@aliyun ~]# 
    

    如果c是左斜杠,不需要转义也可以

    [root@aliyun ~]# sed -rn '/egon/p' test.txt 
    2222222egon
    333333egon
    444444egon
    [root@aliyun ~]# sed -rn '/egon/p' test.txt 
    2222222egon
    333333egon
    444444egon
    [root@aliyun ~]# 
    

    如果匹配的正则里有左斜杠,要么将正则转义,要么将c转义

    [root@aliyun ~]# cat a.txt 
    /etc/egon/666
    etc
    [root@aliyun ~]# sed -rn '//etc/egon/666/p' a.txt # 错误
    sed: -e expression #1, char 0: no previous regular expression
        
    [root@aliyun ~]# sed -rn '//etc/egon/666/p' a.txt  # 正则转义
    /etc/egon/666
    
    [root@aliyun ~]# sed -rn '#/etc/egon/666#p' a.txt # 转义c,必须是c
    [root@aliyun ~]# sed -rn '#/etc/egon/666#p' a.txt  # 转义c
    /etc/egon/666
    [root@aliyun ~]# 
    
    
    # 示例
    [root@aliyun ~]# cat a.txt 
    /etc/egon/666
    etc
    [root@aliyun ~]# sed -ri '//etc/egon/666/s/.*/xxx/' a.txt 
    [root@aliyun ~]# cat a.txt 
    xxx
    etc
    [root@aliyun ~]# 
    

    三 sed常用命令

    sed命令告诉sed对指定行进行何种操作,包括打印、删除、修改等。

    命令			   功能
    a				在当前行后添加一行或多行
    c				用新文本修改(替换)当前行中的文本
    d				删除行
    i				在当前行之前插入文本
    l				会用$符号标识出文件中看不到的字符的位置
    p				打印行
    n				把下一行内容读入模式空间,后续的处理命令处理的都是刚读入的新内容
    q				结束或退出sed,不会将后续内容读入模式空间
    r				从文件中读
    !				对所选行以外的所有行应用命令
    s				用一个字符串替换另一个
    w				将行写入文件
    y				将字符转换为另一字符(不支持正则表达式),y/egon/1234/  e->1 g->2 o->3 n->4
    
    h				把模式空间里的内容复制到暂存缓冲区(覆盖)
    H				把模式空间里的内容追加到暂存缓冲区
    g				取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容
    G				取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面
    x				交换暂存缓冲区与模式空间的内容
    
    替换标志 s
    g				在行内进行全局替换
    i				忽略大小写
    

    sed命令示例

    打印命令:p
    # sed -r "/egon/p" a.txt		
    # sed -r -n "/egon/p" a.txt
    
    删除命令:d,注意用单引号
    # sed -r '3d' a.txt
    # sed -r '3,$d' a.txt
    # sed -r '$d' a.txt
    # sed -r '/egon/d' a.txt 	
    # sed -r '1,/egon/{/egon/d}' a.txt 			# 只删除模式匹配成功的第一行
    
    
    [root@egon ~]# cat a.txt 
    Egon111111
    egon222222
    333Egon333
    444444egon
    5555555555
    6666666666
    egon777777
    8888888888
    [root@egon ~]# 
    [root@egon ~]# sed -r '/egon/d' a.txt  # 只删除模式匹配成功的所有行
    Egon111111
    333Egon333
    5555555555
    6666666666
    8888888888
    [root@egon ~]# sed -r '1,/egon/{/egon/d}' a.txt  # 只删除模式匹配成功的第一行
    Egon111111
    333Egon333
    444444egon
    5555555555
    6666666666
    egon777777
    8888888888
    
    
    替换命令:s
    # sed -r 's/egon/Bigegon/' a.txt 
    # sed -r 's/egon/Bigegon/g' a.txt 
    # sed -r 's/^egon/Bigegon/g' a.txt
    # sed -r -n 's/root/egon/gip' /etc/passwd
    # sed -r 's/[0-9]$/&.change/' a.txt		# &代表取到匹配成功的整行内容
    
    # sed -r 's/^([a-zA-Z]+)([^[a-zA-Z]+)/21/' a.txt
    # sed -r 's#egon#bigegon#g' a.txt			
    
    多重编辑命令:e
    # sed -r -e '1,3d' -e 's/[Ee]gon/EGON/g' a.txt  # 在前一个-e的基础之上进行第二个-e操作
    # sed -r '1,3d;s/[Ee]gon/EGON/g' a.txt
    
    # sed -r '3{s/[0-9]/x/g;s/[Ee]gon/EGON/g}' a.txt  # 只处理第三行
    # sed -r '1,3{s/[0-9]/x/g;s/[Ee]gon/EGON/g}' a.txt  # 处理1到3行
    
    # sed -r -n '1p;p' a.txt  # ;分隔依次运行,先针对第一行进行p操作,再针对所有行进行p操作
    # sed -r -n '1{p;p}' a.txt  # 只针对第一行,连续进行两次p操作
    
    反向选择!
    # sed -r '3d' a.txt
    # sed -r '3!d' a.txt
    
    
    读文件命令:r
    # sed -r '/^Egon/r b.txt' a.txt  # 在匹配成功的行后添加文件b.txt的内容
    # sed -r '/2/r b.txt' a.txt  # 在第2行后面添加文件b.txt的内容
    
    写文件命令:w
    # sed -r '/[Ee]gon/w b.txt' a.txt  # 将匹配成功的行写入新文件b.txt		
    # sed -r '3,$w /root/new.txt' a.txt # 将第3行到最后一行写入/root/new.txt
    
    追加命令:a
    # sed -r '2aXXXXXXXXXXXXXXXXXXXX' a.txt  # 在第2行后添加一行
    # sed -r '2a1111111111111               # 可以用续行
    > 222222222222
    > 333333333333' a.txt
    
    插入命令:i
    # sed -r '2i1111111111111' /etc/hosts
    # sed -r '2i111111111
    > 2222222222
    > 3333333333' a.txt
    
    修改命令:c
    # sed -r '2c1111111111111' a.txt
    # sed -r '2c111111111111
    > 22222222222
    > 33333333333' a.txt
    
    把下一行内容读入模式空间:n
    # sed -r '/^Egon/{n;s/[0-9]/x/g}' a.txt  # 将匹配/^Egon/成功的行的下一行读入模式空间进行s处理
    [root@aliyun ~]# cat a.txt 
    /etc/egon/666
    etc
    [root@aliyun ~]# sed -r '#/etc/egon/666#n;c 1111' a.txt 
    /etc/egon/666
    1111
    [root@aliyun ~]# 
    
    转换命令:y
    # sed -r '1,3y/Eeo/12X/' a.txt  # 1到3行进行转换 对应规则:a->1 e->2 o->X
    
    退出:q
    # sed -r '5q' a.txt 			
    # sed -r '/[Ee]gon/{ s/[0-9]/X/; q; }' a.txt  # 匹配成功/[Ee]gon/则执行{}内命令,q代表退出,即替换一次则退出,如果文件中多行符合规则的内容也只替换了第一个
    

    四 模式空间与保持空间

    sed 有两个内置的存储空间:

    • 模式空间(pattern space):

      如你所知,模式空间用于 sed 执行的正常流程中。该空间 sed 内置的一个缓冲区,用来存放、修改从输入文件读取的内容。

    • 保持空间(hold space):

      保持空间是另外一个缓冲区,用来存放临时数据。Sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。

    我们已经讨论过,每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容则保持不变,不会在循环中被删除。

    模式空间与保持空间的操作命令

    x:命令x(exchange) 用于交换模式空间和保持空间的内容
    
    h:模式空间复制/覆盖到保持空间
    H:模式空间追加到保持空间
    
    g:保持空间复制/覆盖到模式空间
    G:保持空间追加到模式空间
    
    n:读取下一行到/覆盖到模式空间
    N:将下一行添加到模式空间
    
    
    d:删除pattern space中的所有行,并读入下一新行到pattern space中
    

    示例:交换文件的行

    [root@egon ~]# cat test.txt 
    1111
    2222
    3333
    
    # ======================方式1:======================
    [root@egon ~]# tac test.txt 
    3333
    2222
    1111
    [root@egon ~]# 
    
    # ======================方式2:======================
    思路:
    # 1、读取文件第一行内容到模式空间,进行的操作如下  
    # 将模式空间内容覆盖到保持空间
    # 删除模式空间内容
       
    # 2、读取文件第二行内容到模式空间,进行的操作如下  
    # 将保持内容追加到模式空间
    # 将模式空间内容覆盖到保持空间
    # 删除模式空间内容 
    
    # 3、读取文件第三行内容到模式空间,进行的操作如下  
    # 将保持空间内容追加到模式空间
    
    实现:
    sed -r '1h;1d;2G;2h;2d;3G' test.txt
    或者
    sed '1!G;h;$!d' test.txt
    

    五 sed脚本

    sed脚本就是写在文件中的一系列sed命令,使用-f 选项指定sed脚本文件名,需要注意的问题如下

    • 脚本末尾不能有任何多余的空格或文本
    • 如果命令不能独占一行,就必须以结尾
    • 脚本中不能使用引号,除非它们是查找串的一部分
    • 反斜杠起到续行的作用
    [root@egon ~]# cat sed.sh #永久存储,存了多行sed命令,相当于多道关卡,每读入一行内容将经历一道道关卡
    1h;1d;2G;2h;2d;3G
    1h;1d;2G;2h;2d;3G
    
    [root@egon ~]# sed -r '' a.txt
    1111
    2222
    3333
    [root@egon ~]# 
    [root@egon ~]# sed -r -f sed.sh test.txt 
    3333
    2222
    1111
    2222
    1111
    [root@egon ~]# 
    

    六 练习

    
    删除配置文件中用井号#注释的行
    sed -r -i '/^#/d' file.conf 
    sed -r -i '/^[ 	]*#/d' file.conf
    
    删除配置文件中用双斜杠//注释的行 
    sed -r -i 'c//cd' file.conf
    
    删除无内容空行 
    sed -r '/^$/d' file.conf 
    sed -r '/^[	]*$/d' file.conf 
    sed -r '/^[ 	]*$/d' file.conf
    
    
    示例:
    # 删除#号注释和无内容的空行
    sed -r -i '/^[ 	]*#/d; /^[ 	]*$/d' /etc/vsftpd/vsftpd.conf
    sed -r -i '/^[ 	]*#|^[ 	]*$/d' /etc/vsftpd/vsftpd.conf # 同上
    
    追加一行,可有可无,有更清晰
    sed -r -i '$achroot_local_user=YES' /etc/vsftpd/vsftpd.conf 
    
    
    给文件每行加注释
    sed -r -i 's/^/#/' filename
    
    每指定行加注释
    sed -r -i '10,$s/^/#/' filename
    sed -r '3,$s/^#*/#/' filename		# 将行首连续的零个或多个#换成一个#
    
    
    sed中使用外部变量
    # var1=666
    # sed -r 3a$var1 test.txt    # 可以不加引号
    # sed -r "3a$var1" test.txt  # 也可以加引号,但注意是双引号而不是单引号,因为要用$符号取变量值
    # sed -r '3a'"$var1" test.txt # 也可以sed命令用''引起来,而变量用"",注意二者之间不能有空格
    
  • 相关阅读:
    HDU 6182 A Math Problem 水题
    HDU 6186 CS Course 位运算 思维
    HDU 6188 Duizi and Shunzi 贪心 思维
    HDU 2824 The Euler function 欧拉函数
    HDU 3037 Saving Beans 多重集合的结合 lucas定理
    HDU 3923 Invoker Polya定理
    FZU 2282 Wand 组合数学 错排公式
    HDU 1452 Happy 2004 数论
    HDU 5778 abs 数论
    欧拉回路【判断连通+度数为偶】
  • 原文地址:https://www.cnblogs.com/zhaokunhao/p/14930871.html
Copyright © 2011-2022 走看看