【sed】进阶

 
sed的基本用法已能满足大多数需求,但当需要时,知道这些高级特效的存在及如何使用将提供莫大的帮助!
 
1. 多行命令
        sed编辑器提供三个用于处理多行文本的特殊命令:
  • N:将数据流的下一行加入当前模式空间   
  • D:删除多行组中的一行
  • P:打印多行组中的一行
 
    【next命令】
         
        单行next命令:
            小写的n命令,将下一行文本移入模式空间(工作空间)并挤走已有文本,即跳过当前行进入下一行。
1 # cat data1.txt
2 this is the header line
3 
4 this is the data line
5 
6 this is the last line

            经n命令处理后可跳过第一行:

1 # sed '/header/{n;d}' data1.txt   
2 this is the header line
3 this is the data line
4  
5 this is the last line

               

           多行next命令:
                大写的N命令,将下一行文本并入当前模式空间,即加到已有文本之后。两个文本行合并成一行,仍以换行符分隔。
1 # cat data2.txt
2 This is the header line.
3 This is the first data line.
4 This is the second data line.
5 This is the last line.
                经N命令处理后:
1 # sed '/first/{N;s/
/ /}' data2.txt   
2 This is the header line.
3 This is the first data line.  This is the second data line.
4 This is the last line.

                Tips:使用N命令可查找分散在两行的文本。注意最后一行进入模式空间,执行N命令由于没有后续的可读入行,会导致后面的命令无法执行。

 
        【多行删除命令】
                单行删除命令d和N命令一起使用时,会将模式空间的文本全部删除;
                多行删除命令D,只删除模式空间的第一行,即删除到换行符为止的所有字符(包含换行符)。
 1 # cat data5.txt
 2  
 3 This is the header line.
 4 This is a data line.
 5  
 6 This is the last line.
1 # sed '/^$/{N ; /header/D}' data5.txt
2 This is the header line.
3 This is a data line.
4 
5 This is the last line.

    Tips:这种办法可实现删除特殊行,比如需要同时满足两种条件的行。

 
            【多行打印命令】
                    单行打印命令会打印出模式空间内的所有文本;
                    多行打印命令仅打印多行模式空间的第一行,即打印换行符之前的所有字符。
1 # sed -n '/header/{N;P}' data5.txt
2 This is the header line.
 
 
2. 保持空间
    sed编辑器除了模式空间(patten space)外,还有一个保持空间(hold space)。处理模式空间的某些行时,可以使用保持空间临时保存一些行。
 
命令
描述
h
H
g
G
x
将模式空间复制到保持空间
将模式空间附加到保持空间
将保持空间复制到模式空间
将保持空间附加到模式空间
交换模式空间和保持空间
        读懂以下命令,理解保持空间用法:
1 # sed -n '/first/ {h ; p ; n ; p ; g ; p }' data2.txt
2 This is the first data line.
3 This is the second data line.
4 This is the first data line.
3. 排除命令
       感叹号命令(!)用于排除某个命令,即让原本的命令不起作用。
1 # sed -n '/header/p' data2.txt  
2 This is the header line.

        普通p命令打印匹配文本行,使用!后,效果相反,不打印该行而打印其它行:

1 # sed -n '/header/!p' data2.txt
2 This is the first data line.
3 This is the second data line.
4 This is the last line.

        结合保持空间反转文本行的顺序:

1 # sed -n '{1!G ; h ; $p }' data2.txt
2 This is the last line.
3 This is the second data line.
4 This is the first data line.
5 This is the header line.

        Tips:sed编辑器默认会将命令循环应用在每一行文本上,因此合理使用命令,可写出简洁高效的sed脚本

 
 
4. 改变流
      sed编辑器提供了改变脚本执行流程的方法。
 
        【分支】
            分支(branch)命令(b)可只对数据流中的特定行执行命令。
 
            格式:
                    [address]b     [label]
                     address参数定义触发分支的行数,label参数用于定义要跳转的位置。若没有加label,则会跳过脚本。
            
            加address,不加label,跳过后面所有脚本:
1 # sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' data2.txt
2 Is this the header test?
3 This is the first data line.
4 This is the second data line.
5 Is this the last test?

            加address,加label,分支匹配处的行跳到标签处,执行标签后的命令;不匹配的行执行所有命令:

1 # sed '/first/b jump1 ; s/This is the/No jump on/; :jump1 ; s/This is the/Jump here on/' data2.txt
2 No jump on header line.
3 Jump here on first data line.
4 No jump on second data line.
5 No jump on last line.

            不加address,b命令无条件跳转到标签上,可造成循环的效果:

1 # echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//1p;b start}'
2 This is, a, test, to, remove, commas.
3 This is a, test, to, remove, commas.
4 This is a test, to, remove, commas.
5 This is a test to, remove, commas.
6 This is a test to remove, commas.
7 This is a test to remove commas.
8 ^C

            该脚本不会停止循环,可使用/,/b start代替b start,在没有逗号时自动结束循环。

 
        【测试】
            测试(test)命令(t)会根据替换(s)命令的结果来跳转到某个标签。
 
            不加label,跳过后面所有命令:
1 # sed 's/first/matched/; t ; s/This/Here/' data2.txt          
2 Here is the header line.
3 This is the matched data line.
4 Here is the second data line.
5 Here is the last line.

            加label,跳转到label处:

1 # echo "This,is,a,test,to,remove,commas." | sed -n '{:start ; s/,/ /p ; t start}'
2 This is,a,test,to,remove,commas.
3 This is a,test,to,remove,commas.
4 This is a test,to,remove,commas.
5 This is a test to,remove,commas.
6 This is a test to remove,commas.
7 This is a test to remove commas.
1 # sed 's/first/matched/; t ;s/This/Here/;s/line/LINE/' data2.txt      
2 Here is the header LINE.
3 This is the matched data line.
4 Here is the second data LINE.
5 Here is the last LINE.
1 # sed 's/first/matched/; t jump ;s/This/Here/; :jump ;s/line/LINE/' data2.txt
2 Here is the header LINE.
3 This is the matched data LINE.
4 Here is the second data LINE.
5 Here is the last LINE.

            Tips:使用标签和t命令可在脚本命令中形成循环

 
5. 模式替代
 
        【&符号】
            &符号可以提取命令中匹配模式中的全部文本。
1 # echo "The cat sleeps in his hat." | sed 's/.at/"&"/g'
2 The "cat" sleeps in his "hat".

         

   【替代单独的单词】

            用圆括号来定义子模式,在替换模式中用1等引用子模式,可提取匹配模式中的部分文本。
1 # echo 1234567 | sed ':start;s/(.*[0-9])([0-9]{3})/1,2/;t start'
2 1,234,567

            Tips:圆括号必须转义

  
6. 重定向sed输出
            
            【    $()    】
                默认情况,sed会将脚本结果输出到STDOUT,可使用$()将输出保持到变量中。和变量替换一样