• 文本三剑客之sed


    sed是一个流编辑器(sed是stream editor的缩写),它可以对从标准输入流中得到的数据进行处理,然后把处理以后得到的结果输出到标准输出,而标准输出通常会关联到终端屏幕,因此处理后的结果也会显示到屏幕上。当然,也可以把标准输出重定向到文件,这样处理后的结果就会保存在磁盘文件中。

    格式:

    sed    [OPTION]    '/pattern/action'    FILE1,FILE2…      #/pattern/action  即可使用单引号, 也可使用双引号(双引号支持变量的引用)

    可看出sed同样可以同时处理多个文件

    注意:

    sed只会对流经它的数据流进行处理和编辑,而不会对原始文件做任何修改(如果要对原始文件进行修改可使用 -i 选项),这就意味着sed要处理的数据并不一定非要是磁盘上的文件,也可以是其他进程的数据输出

    sed命令通常有两种调用形式: 

    1) 直接从管道中读取输入数据

     cmd1  |   sed 'cmd'

    2) 直接读取文件内容

      sed  'cmd'   file1[,file2,file3...] 

    Sed获取数据流的两种方式:管道和文件

    sed命令执行时,它会从输入文件(或标准输入数据流中)每次读取一行数据,并把这行数据复制一份保存在它内部的(缓存)模式空间中(也即是说sed每次按行处理数据,每次处理1)。

    所有的数据都是在这个缓存中被处理的,然后sed命令会根据指定的编辑命令对缓存中的数据进行处理。当这行数据处理完以后,sed命令会读取下一行数据,重复整个过程,直到所有的数据被处理完为止

    sed命令的主要特性:

    使用相同的一系列操作重复地处理文件中的每一行文本,当文件中的所有行都被sed命令处理完以后,文件被关闭,然后sed命令退出。

    Pattern说明:

    pattern是一个正则表达式pattern两侧的斜杠/作为分隔符限定了正则表达式的起始和结束的位置通过这个正则表达式可以匹配要操作的是文件(或数据)中的行,只有正则表达式pattern匹配的行,sed命令才会在模式空间中对它进行处理。

    如果不写正则表达式/pattern/sed会对输入数据的所有行都会一行一行的执行action操作

    /pattern/          #选择(匹配)操作的行

    可以理解为地址,所谓地址就是文本文件的行号正则,要么是一个文件中的特定行,要么是一个范围。如果在编辑命令中没有指定地址,则sed命令会对每一行都执行编辑操作

    sed中进行输出时包含指定地址的两端的行常用形式如下:(^表示行开始,$表示行尾)

    1sed    -n    '3p'    /etc/passwd

    2sed    -n    '3,10p'     /etc/passwd

    注意:指定一个地址范围时,起始行的行号总是应该小于结束行的行号,否则仅会输出行号最大的一行,如:sed  -n  ‘263p’  /etc/passwd    #仅会输出第26

    3sed    -n    '3+10p'    /etc/passwd            #输出第3行,及后面的10

    4sed    -n    '326p'   /etc/passwd            #输出3~26行之外的所有行

    5sed    -n    '1~2p'   /etc/passwd                #输出所有奇数行(~2表示步长增量)

    6sed    -n    '/root/p'   /etc/passwd              #输出包含root的行

    7sed    -n   '2/root/p'    /etc/passwd           #行号和正则混合,仅匹配第一个遇到正则

    8sed    -n   '/root/,/root/p'    /etc/passwd 

    #假设该文件中有很多个root行,则会按照如下方式输出:

    第1个包含root的行和第2个包含root的行之间的所有内容,

    第2个包含root的行和第3个包含root的行之间的内容不输出

    输出第3个包含root的行和第4个包含root的行之间的所有内容,

    第4个包含root的行和第5个包含root的行之间的内容不输出

    输出第5个包含root的行和第6个包含root的行之间的所有内容,

    action的说明

    action是对正则表达式pattern过滤出来的行进行处理的动作

    1)   a             在指定行的后面添加一行或多行文本(追加多行之间可以用 来换行)

    示例:      

    [root@scm ~]$ sed '3afirst line
    second line' test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    first line
    second line
    104,weak4,Test4

    [root@scm ~]$ sed '/103/afirst line second line' test.txt
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    first line
    second line
    104,weak4,Test4

    [root@scm ~]$ sed '3a$pid' test.txt
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    $pid                             #单引号不支持变量扩展
    104,weak4,Test4
    [root@scm ~]$ sed "3a$pid" test.txt       
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    1456                             #双引号支持变量扩展
    104,weak4,Test4

    2)  i         在指定行的前面插入一行或多行文本               #多行使用 分隔

    [root@scm ~]$ cat test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ sed '3ifirst line
    second line' test.txt        
    101,weak1,Test1
    102,weak2,Test2
    first line
    second line
    103,weak3,Test3
    104,weak4,Test4

    3)  c        用新行替换指定的旧行

    [root@scm ~]$ cat test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ sed '3c103,103,103' test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,103,103
    104,weak4,Test4

    4)  d        删除指定的行                                #功能

    [root@scm ~]$ cat test.txt                 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ sed '3d' test.txt 
    101,weak1,Test1
    102,weak2,Test2
    104,weak4,Test4

     5)  =            输出每个匹配行的行号(在行号的下一行输出该行的内容),如果结合 -n 选项一同使用,只显示行号,不显示内容 

    [root@scm ~]$ sed '1,3='  test.txt  
    1
    101,weak1,Test1
    2
    102,weak2,Test2
    3
    103,weak3,Test3
    104,weak4,Test4

    6)  l             显示不可打印字符                    #注意这个字符是英文字母L的小写

    [root@scm ~]$ sed  -n  '1,3l'  test.txt 
    101,weak1,Test1$
    102,weak2,Test2$
    103,weak3,Test3$

    7) p            打印处理的行   

    [root@scm ~]$ sed  -n  '1,3p'  test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3

    8)  y/1234/abcd/      字符转换, 类似tr指令, 将匹配行中的1234是个字符转换为abcd, 也可用于大小写转换

    [root@scm ~]$ cat test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ sed 'y/1234/ABCD/' test.txt    
    A0A,weakA,TestA
    A0B,weakB,TestB
    A0C,weakC,TestC
    A0D,weakD,TestD

    9) r  FILE         将一个文本文件中的内容追加到当前文件的特定位置上

    [root@scm ~]$ cat test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ cat file 
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    [root@scm ~]$ sed '3rfile'  test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    104,weak4,Test4

    10) w  FILE      将一个文本文件中的内容写入到当前文件的特定位置上(会修改FILE文件)

    [root@scm ~]$ cat file 
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    [root@scm ~]$ cat test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ sed '2,3 w file'  test.txt 
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4
    [root@scm ~]$ cat file 
    102,weak2,Test2
    103,weak3,Test3

    11)  s/regexp/replacement/id            替换                   #sed最常用的功能, 默认只会替换一行中的第一个匹配字符,除非指定g全局替换

    分隔不一定要使用/,可以使用其它任何字符,sed会将s后的第一个字符作为分隔符

    regexp是行内要匹配的字段

    replacement将正则匹配的字段替换为该字段

    id指定替换动作的行为, 常用的id标识如下: 

    g  全局替换, 默认s动作仅会替换每行中的第一个匹配字段, 如果一行中有多个相同的字段都要替换, 则需要使用g标记

    [root@scm ~]$ cat test.txt 
    101,test1,weak1,Test1,test1
    102,test2,weak2,Test2,test2
    103,test3,weak3,Test3,test3
    104,test4,weak4,Test4,test4
    [root@scm ~]$ sed 's#test#TEST#g'  test.txt 
    101,TEST1,weak1,Test1,TEST1
    102,TEST2,weak2,Test2,TEST2
    103,TEST3,weak3,Test3,TEST3
    104,TEST4,weak4,Test4,TEST4
    [root@scm ~]$ sed 's#test#TEST#'  test.txt  
    101,TEST1,weak1,Test1,test1
    102,TEST2,weak2,Test2,test2
    103,TEST3,weak3,Test3,test3
    104,TEST4,weak4,Test4,test4

    i或I  忽略大小写

    [root@scm ~]$ cat test.txt 
    101,test1,weak1,Test1,test1
    102,test2,weak2,Test2,test2
    103,test3,weak3,Test3,test3
    104,test4,weak4,Test4,test4
    [root@scm ~]$ sed 's#test#TEST#g'  test.txt  
    101,TEST1,weak1,Test1,TEST1
    102,TEST2,weak2,Test2,TEST2
    103,TEST3,weak3,Test3,TEST3
    104,TEST4,weak4,Test4,TEST4
    [root@scm ~]$ sed 's#test#TEST#gi'  test.txt 
    101,TEST1,weak1,TEST1,TEST1
    102,TEST2,weak2,TEST2,TEST2
    103,TEST3,weak3,TEST3,TEST3
    104,TEST4,weak4,TEST4,TEST4

    [root@scm ~]$ sed 's#test#TEST#gI' test.txt
    101,TEST1,weak1,TEST1,TEST1
    102,TEST2,weak2,TEST2,TEST2
    103,TEST3,weak3,TEST3,TEST3
    104,TEST4,weak4,TEST4,TEST4

    NUM      仅对每行的第NUM个匹配进行替换, 如果和g标记配合使用, 可实现第NUM个及其之后的所有匹配字段全部替换

    [root@scm ~]$ cat test.txt 
    101,test1,weak1,Test1,test1
    102,test2,weak2,Test2,test2
    103,test3,weak3,Test3,test3
    104,test4,weak4,Test4,test4
    [root@scm ~]$ sed 's#test#TEST#i2'  test.txt 
    101,test1,weak1,TEST1,test1
    102,test2,weak2,TEST2,test2
    103,test3,weak3,TEST3,test3
    104,test4,weak4,TEST4,test4
    [root@scm ~]$ sed 's#test#TEST#i2g'  test.txt 
    101,test1,weak1,TEST1,TEST1
    102,test2,weak2,TEST2,TEST2
    103,test3,weak3,TEST3,TEST3
    104,test4,weak4,TEST4,TEST4

    p    匹配成功打印模式空间

    w  FILE      匹配成功将结果写入文件FILE

    [root@scm ~]$ sed 's#test#TEST#i2w test1.txt'  test.txt 
    101,test1,weak1,TEST1,test1
    102,test2,weak2,TEST2,test2
    103,test3,weak3,TEST3,test3
    104,test4,weak4,TEST4,test4
    
    [root@scm ~]$ cat test1.txt 
    101,test1,weak1,TEST1,test1
    102,test2,weak2,TEST2,test2
    103,test3,weak3,TEST3,test3
    104,test4,weak4,TEST4,test4

    &    特殊变量,存储/regexp/匹配的内容

    [root@scm ~]$ echo 'am a linuxer' | sed 's#am#--&--#g'        #后面的&就等同于am
    --am-- a linuxer

    e      表示执行指令

    x     交换暂存缓冲区与模式空间的内容

    y     将字符转换为另一字符(不能对正则表达式使用y 命令)

    分组替换 

    跟在正则表达式中一样, sed 中也可以 使用分组,   以  ( 开始,以 ) 结束(因为()是扩展的正则, 因此需要使用进行转义, 如果不想使用转义, 可使用-r选项, 即使用扩展的正则),  分组可以用在 后向引用中

    
    

    [root@scm ~]$ echo "The Geek Stuff"|sed 's#([A-Z])#(1)#g'
    (T)he (G)eek (S)tuff
    [root@scm ~]$ echo "The Geek Stuff"|sed -r 's#([A-Z])#(1)#g'     #-r选项支持扩展的正则表达式

    (T)he (G)eek (S)tuff

    [root@scm ~]# cat test.txt
    101,weak1,Test1
    102,weak2,Test2
    103,weak3,Test3
    104,weak4,Test4

    [root@scm ~]# sed -r 's#^([^,]*),([^,]*),([^,]*)#1,3#' test.txt
    101,Test1
    102,Test2
    103,Test3
    104,Test4

    [root@scm ~]# sed -r 's#^([0-9]*),([a-zA-Z0-9]*),([a-zA-Z0-9]*)#1,3#' test.txt
    101,Test1
    102,Test2
    103,Test3
    104,Test4

     

    注意:  sed最多能处理 9个分组,分别用 1至9表示

    h            把模式空间里的内容复制到暂存缓存区

    H            把模式空间里的内容追加到暂存缓存区

    g            取出暂存缓冲区里的内容,将其复制到模式空间,覆盖该处原有内容

    G            取出暂存缓冲区里的内容,将其复制到模式空间,追加在原有内容后面        #这4个选项不常用

      

    n            读入下一输入行,并从下一条命令而不是第一条命令开始处理

    常用选项Option:

    -n           限制仅输出被处理的行,而不是将读取到模式空间中的所有行全部输出

    -r            支持使用扩展正则表达式(默认情况下sed仅使用基础正则表达式,使用该选项可使用扩展的正则表达式)

    -i            默认sed仅会更改显示的内容,不会更改实际文件,该项将会更改文件的实际内容

    多个匹配处理:4种方法

    法一: 

    -e  '/pattern/action’   -e  ‘/pattern/action …'           #-e选项指定多个匹配,grep也有这种用法

    法二: 

    -f  script-file                               #-e类似,只是将多个pattern写入到文件中(每行一个匹配), 如果配合-n选项使用, 不能写成-fn(要写成-nf)

    法三: 

    '/pattern/action; /pattern/action; /pattern/action…'         #使用分号指定多个匹配

    法四:

    {
      /pattern/action
      /pattern/action
      ....
    }     ....

    注意:

    1最后2种:分号;和{  }指定,两条命令的执行是有前后顺序的,第二条命令不会在第一条之前执行,并且它接收到的数据总是第一条命令处理以后的结果

    2、如果想指定两个独立的编辑命令,分别为两个编辑命令指定选项-e

    3、在-f后接的文件中。可以像在Shell脚本中一样添加注释,在要注释的行前面添加字符#,从字符#到下一个换行符之间的全部内容都会被认为是注释,不会被匹配

     

  • 相关阅读:
    工作错误记录javac找不到
    蜜柚系统离备份文件解密
    如何备份蜜柚桌面!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    Excel表导入数据库
    ReportViewer和 rdlc报表使用小记
    自定义天气WCF服务接口
    Windows平台下SVN安装配置及使用
    SQLServer 2012 Always on配置全过程
    处理check选中后鼠标悬停问题
    js MD5加密
  • 原文地址:https://www.cnblogs.com/wyzhou/p/9313903.html
Copyright © 2020-2023  润新知