zoukankan      html  css  js  c++  java
  • Sed命令详解及应用实例

    第一部分:Sed基本用法

    sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。

    sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。下面先来预览下sed的常用命令及参数。

    1. p命令.

    p命令用于输出匹配行的内容,比如test.txt文件的内容如下,后续说明均已此文件内容来加以说明

    viidiot@ubuntu:~/Desktop$ cat test.txt

    line one

    line two

    Hi,everybody,i'm linux-code!

       Linux-code,to be the best one!


    单纯的p命令会输出如下,即含有Hi的行被输出了两次。

    viidiot@ubuntu:~/Desktop$ sed '/Hi/p' test.txt

    line one

    line two

    Hi,everybody,i'm linux-code!

    Hi,everybody,i'm linux-code!

       Linux-code,to be the best one!


    如果在p命令的基础上,加上-n选项,可以输出含有特定模式的行,如下命令则输出test.txt文件中含有模式Hi的行。

    viidiot@ubuntu:~/Desktop$ sed -n '/Hi/p' test.txt

    Hi,everybody,i'm linux-code!

    2. d命令

    d命令用于删除特定行。

    比如要删除test.txt中第一二行,其命令如下:

    viidiot@ubuntu:~/Desktop$ sed '1,2d' test.txt

    Hi,everybody,i'm linux-code!

       Linux-code,to be the best one!


    若要删除最后一行,命令如下:

    viidiot@ubuntu:~/Desktop$ sed '$d' test.txt

    line one

    line two

    Hi,everybody,i'm linux-code!


    同理,删除含有linux-code的行:

    viidiot@ubuntu:~/Desktop$ sed '/linux-code/d' test.txt

    line one

    line two

       Linux-code,to be the best one!


    3. S命令

    s命令用于文本替换。

    比如,要将test.txt文件中的Linux-code替换成Viidiot

    viidiot@ubuntu:~/Desktop$ sed 's/Linux-code/Viidiot/g' test.txt

    line one

    line two

    Hi,everybody,i'm linux-code!

       Viidiot,to be the best one!

    注意后面那个g参数。g表示多次匹配,如果不加g参数,若某一行有多个匹配在字符串,只替换掉第一次匹配的。


    替换以line开头的行第一个单词替换为linux-code

    viidiot@ubuntu:~/Desktop$ sed 's/^line/linux-code/' test.txt

    linux-code one

    linux-code two

       Hi,everybody,i'm linux-code!linux-code!

       Linux-code,to be the best one!


    替换以line开头的行最后一个单词替换为linux-code

    viidiot@ubuntu:~/Desktop$ sed 's/one$/linux-code/' test.txt

    line linux-code

    line two

       Hi,everybody,i'm linux-code!linux-code!

       Linux-code,to be the best one!


    如果需要将以line开头的行全部替换掉,而不是仅仅替换掉一个单词怎么做呢?后面接.*表示通配的意思,也即^line.*表示以line开头,后接0个或多个任意字符。

    viidiot@ubuntu:~/Desktop$ sed 's/^line.*/linux-code/' test.txt

    linux-code

    linux-code

       Hi,everybody,i'm linux-code!linux-code!

       Linux-code,to be the best one!


    4. e选项

    -e即edit的意思,编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。

    viidiot@ubuntu:~/Desktop$ sed -e '1,2d' -e 's/linux-code/Linux/' test.txt

       Hi,everybody,i'm Linux!linux-code!

       Linux-code,to be the best one!

    上述为sed命令使用选项-e进行多重编辑后得到的结果。第一重编辑删除第1、2行。第二重编辑将出第1、2行外的所有linux-code替换为Linux。因为是逐行进行这两项编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果。


    5. r命令

    r命令是读命令。sed使用该命令将一个文本文件中的内容加到当前文件的特定位置上。

    viidiot@ubuntu:~/Desktop$ sed '/linux-code/r test1.txt' test.txt

    line one

    line two

       Hi,everybody,i'm linux-code!linux-code!

    linux-code

    be perfect!

       Linux-code,to be the best one!

    上述命令的意思是:如果在文件test.txt的某一行匹配到模式linux-code,就在该行后读入文件test1.txt的内容。如果包含linux-code的行不止一行,则在出现linux-code的各行后都读入test1.txt文件的内容。


    6. w命令

    viidiot@ubuntu:~/Desktop$ sed '/code/w test1.txt' test.txt

    上述命令将test.txt文件中包含模式code的行内容写入到test1.txt。

    7. a命令

    a命令将添加新文本到文件中当前行(即读入模式缓冲区中的行)的后面。所追加的文本行位于sed命令的下方另起一行。如果要追加的内容超过一行,则每一行都必须以反斜线结束,最后一行除外。最后一行将以引号和文件名结束。

    viidiot@ubuntu:~/Desktop$ cat test1.txt

       Hi,everybody,i'm linux-code!linux-code!

       Linux-code,to be the best one!

    通过a命令将含有模式everybody的行后面加入一行:why ?

    viidiot@ubuntu:~/Desktop$ sed '/everybody/a why ?' test1.txt

       Hi,everybody,i'm linux-code!linux-code!

    why ?

       Linux-code,to be the best one!


    8.i命令

    i命令与a命令相反,它是在匹配行的前面插入一行。

    viidiot@ubuntu:~/Desktop$ sed '/everybody/i you are beautiful' test1.txt

    you are beautiful

       Hi,everybody,i'm linux-code!linux-code!

       Linux-code,to be the best one!


    9. c命令

    c命令将匹配行修改成我们设定的内容。如下则将test1.txt中含有everybody的行修改为you are beautiful

    viidiot@ubuntu:~/Desktop$ sed '/everybody/c you are beautiful' test1.txt

    you are beautiful

       Linux-code,to be the best one!

    10. y命令

    y命令与UNIX/Linux中的tr命令类似,字符按照一对一的方式从左到右进行转换。例如,y/abc/ABC/将把所有小写的a转换成A,小写的b转换成B,小写的c转换成C。

    viidiot@ubuntu:~/Desktop$ sed 'y/code/CODE/' test1.txt

       Hi,EvErybODy,i'm linux-CODE!linux-CODE!

       Linux-CODE,tO bE thE bEst OnE!

    将对应小写字母全部替换成其大写字母。


    第二部分:Sed脚本

    通过编写脚本我们可以方便的批量执行命令。sed脚本就是写在文件中的一系列sed命令。sed脚本中,要求命令的末尾不能有任何多余的空格或文本。如果在一行中有多个命令,要用分号分隔。执行脚本 时,sed先将输入文件中第一行复制到模式缓冲区,然后对其执行脚本中所有的命令。每一行处理完毕后,sed再复制文件中下一行到模式缓冲区,对其执行脚 本中所有命令。使用sed脚本时,不再用引号来确保sed命令不被shell解释。

    举例:我们现在来完成如下任务

    在test1.txt中的开头插入一行欢迎词:Welcome to linux-code

    在末尾加入一行:good bye!

    将文章中所有code替换成CODE。

    那么我们可以编写一个名为sedscript脚本,脚本具体内容如下:

    viidiot@ubuntu:~/Desktop$ cat sedscript

    1iWelcome to linux-code

    s/code/CODE/g

    $agoodbye!

    然后再将sed脚本应用到test1.txt文件上

    viidiot@ubuntu:~/Desktop$ sed -f sedscript test1.txt

    Welcome to linux-code

       Hi,everybody,i'm linux-CODE!linux-CODE!

       Linux-CODE,to be the best one!

    goodbye!

    第三部分:练习题

    学习了sed的基本知识,现在我们来检验下成果吧!呵呵。。。

    1、Sed中如何替换多行中的有规律的数字字符串 

    输入:

    hello world balabala - . gene_id "240838 "; transcript_id "240838";

    hello world balabala again - . gene_id "240838 "; transcript_id "240838";

    balaba….

    输出:

    hello world balabala - . gene_id "zgg240838 "; transcript_id "zgg240838";

    hello world balabala again - . gene_id "zgg240838 "; transcript_id "zgg240838";

    balaba…

    也即,将字符gene_id“后接数字以及transcript_id "后接数字中的引号与数字之间插入zgg字符串。

    脚本编写:

     sed  's/gene_id "([0-9]+)"; transcript_id "([0-9]+)";/gene_id "zgg1"; transcript_id "zgg2";/g' test.txt

    注:1. 数字的匹配[0-9]

    2.[0-9]后接+表示匹配一个或多个数字

    3.匹配部分加括号,引用匹配部分用1,2,....等等。

    4.sed执行多个匹配用分号连接,整个命令用’’引在内部。

    2、在文本中每一行添加行头行尾

    比如test.txt 内容如下所示:

    viidiot@ubuntu:~/Desktop$ cat test.txt

    line one

    line two

    line three

    line four

    1)在每行文字开头添加文字“Viidiot ”:

    viidiot@ubuntu:~/Desktop$ sed '/./s/^/Viidiot /g' test.txt

    Viidiot line one

    Viidiot line two

    Viidiot line three

    Viidiot line four

    2)末尾添加文字“ Viidiot”:

    viidiot@ubuntu:~/Desktop$ sed '/./s/$/ Viidiot/g' test.txt

    line one Viidiot

    line two Viidiot

    line three Viidiot

    line four Viidiot

    3、利用sed进行格式转换

    比如需要将text.txt中如下内容

       dn: uid=admin,ou=ITaccounts,dc=tc
       uid: admin
       cn: admin cn
       sn: admin sn


       dn: uid=0037,ou=employees,dc=tci
       uid: 0037
       cn: thinker
       sn: zzz


    转换成xml格式如下:
       <entity>
       <dn>uid=admin,ou=ITaccounts,dc=tc</dn>
         <uid>admin</uid>
         <cn>admin cn</cn>
       <sn>admin sn</sn>
       </entity>
       <entity>
       <dn>uid=0037,ou=employees,dc=tci</dn>
         <uid>0037</uid>
         <cn>thinker</cn>
         <sn>zzz</sn>
         </entity>


    则可以定义下面的sedscript文件:
    /^dn:[[:space:]]/i
    <entity>
    s/^dn:[[:space:]](.*)$/<dn>1</dn>/g
    s/^uid:[[:space:]](.*)$/<uid>1</uid>/g
    s/^cn:[[:space:]](.*)$/<cn>1</cn>/g
    s/^sn:[[:space:]](.*)$/<sn>1</sn>/g
    s/^$/</entity>/g
    第一行和第二行实现的功能就是在每个dn:开头的行前面加上一行<entity>。最后一行是碰到空行补上</entity>这 个结束标记。

    另外,在执行替换的时候可以通过使用()把被替换的字符串分组,在替换的部分里面用1、2这种方式引用被替换文字里面的相应的组。

    用这种方法把ldif文件里面[:]前的东西删掉并且在两边增加相应的xml标记。
    仔细想想,4行替换也许用下面的1行就能实现?
    s/^(.*):[[:space:]](.*)$/<1>2</1>/g

    viidiot@ubuntu:~/Desktop$ sed -f sedscript test.txt

    <entity>

    <dn>uid=admin,ou=ITaccounts,dc=tc</dn>

    <uid>admin</uid>

    <cn>admin cn</cn>

    <sn>admin sn</sn>

    <entity>

    <dn>uid=0037,ou=employees,dc=tci</dn>

    <uid>0037</uid>

    <cn>thinker</cn>

    <sn>zzz</sn>


    4、在匹配的行前面插入一行

    viidiot@ubuntu:~/Desktop$ cat test.txt

    line one

    line two

    Hi,everybody,i'm linux-code!

       Linux-code,to be the best one!

    将以空格开头的行前面插入一行文字:a new paragraph

    viidiot@ubuntu:~/Desktop$ sed '/^[[:space:]]/i   a new paragraph'  test.txt

    line one

    line two

    a new paragraph

    Hi,everybody,i'm linux-code!

    a new paragraph

       Linux-code,to be the best one!


    5、在文章中每一行前加上行号

    此题是由sed引入的题外话。用sed怎么去完成?读者自己开动开动脑筋吧!

    在文章中每一行加上行号的方法有很多,比如,我们可以这样:

    viidiot@ubuntu:~/Desktop$ nl test.txt

         1 line one

         2 line two

         3 Hi,everybody,i'm linux-code!

         4    Linux-code,to be the best one!

    也可以这样:

    viidiot@ubuntu:~/Desktop$ cat -n test.txt

         1 line one

         2 line two

         3 Hi,everybody,i'm linux-code!

         4    Linux-code,to be the best one!

    还可以这样:

    viidiot@ubuntu:~/Desktop$ awk '{print NR, $0}' test.txt

    1 line one

    2 line two

    3  Hi,everybody,i'm linux-code!

    4    Linux-code,to be the best one!

    所以,如果需要在文本test.txt中永久的插入行号并存档,你也行可以这样:

    viidiot@ubuntu:~/Desktop$ cat -n test.txt >>tmp.txt;mv tmp.txt test.txt

    viidiot@ubuntu:~/Desktop$ cat test.txt

         1 line one

         2 line two

         3 Hi,everybody,i'm linux-code!

         4    Linux-code,to be the best one!


    本文就这么多了,最后留下一个实践内容,编写一个名叫highlightcode.sh程序,将一个原始的c程序,用sed将它进行格式化,使其能够高亮显示关键字。当然,你可以用纯c/c++去完成这个功能,但脚本可能可以更快的编写出来(相对于c程序)。(注:高亮是指其在浏览器中显示的效果。这里牵涉到css样式文件,并据此在原文件的基础上,插入一些样式,使其能高亮显示)

    原始的显示效果:

    image

    高亮后的显示效果:

    image

    作者:Viidiot(阿呆) 微信公众号:linux-code

    本文链接:http://www.cnblogs.com/jjdiaries/p/3377875.html

    转载请保留作者及链接

  • 相关阅读:
    Unity3d与Android交互
    A star 寻路
    网络协议
    数据驱动
    有限状态机(FSM)
    自己封装一个Log模块
    Unity5.x版本AssetBundle加载研究
    Unity5.x版本AssetBundle打包研究
    alidoing --使用JS实现多语言框架、喜欢的请进、、瓦特平台!
    使用代码生成器“代码工厂”快速生成B/S程序代码
  • 原文地址:https://www.cnblogs.com/jjdiaries/p/3377875.html
Copyright © 2011-2022 走看看