模式空间与保持空间

模式空间与保持空间

sed在正常情况下将处理的行读入模式空间(pattern space),脚本
的"sed command"就是一条接着一条进行处理,直到脚本执行完毕,然后该行被输出,模式被清空,接着重复执行刚才的动作,文件中新的一行被读入,直到文件处理完毕。

工作模式:模式空间和保持空间介绍
    模式空间:初始化为空,处理完一行后会自动输出到屏幕并清除模式空间。
    保持空间:初始化为一个空行,也就是默认带一个\n,处理完后不会自动清除。
模式空间:可以想成工程里面的流水线,数据之间在它上面进行处理,用于处理文本行。
保持空间:可以想象成仓库,我们在进行数据处理的时候,
作为数据的暂存区域,用于保留文本行,是保存已经处理过的
输入行,默认有一个空行。


    #sed -e ‘s/pig/cow/’ -e ‘s/cow/horse/’
    #sed  '1{p;p}' a.txt
    11111111
    11111111
    11111111
    22222222
    33333333
    44444444
    55555555
    66666666

    置换:模式空间和保持空间(暂存空间)
      h 把模式空间内容覆盖到保持空间中
      H 把模式空间内容追加到保持空间中
      g 把保持空间内容覆盖到模式空间中
      G 把保持空间内容追加到模式空间中
      x 交换模式空间与保持空间的内容
[root@localhost ~]# sed 'G' test.txt
1111111

222222222

33333333

444444444

5555555555

666666666

777777777


[root@localhost ~]# cat test.txt
1111111
222222222
33333333
444444444
5555555555
666666666
777777777
》》将1,2,3(2,3是追加进去的)行模式空间的放到保持空间,在将保持空间里的三行追加到第四行的模式空间里
[root@localhost ~]# sed '{1h;2,3H;4G}' test.txt
1111111
222222222
33333333
444444444
1111111
222222222
33333333
5555555555
666666666
777777777

    [root@localhost ~]# sed  '{1h;2x;3g;$G}'  test.txt
1111111
1111111
222222222
444444444
5555555555
666666666
777777777
222222222


    反转:
    /1/{
    h
    d
    }
    /2/{
    G
    }

控制流
      !  命令取反 例: 1!d 删除第一行以外的行
      {} 命令组合 命令用分号分隔 {1h;G} 可以理解为 -e 参数的另一种写法
      =  打印行号(输入行的号码,而非处理的次数行号) 例如: sed -n '2{=;p}' infile
      n  读入下一行到模式空间 例:'4{n;d}' 删除第5行
      N  而是追加下一行到模式空间,再把当前行和下一行同时应用后面的命令
          P  输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出。
          P命令经常出现在N命令之后和D命令之前。
      D  删除模式空间中直到第一个换行符的内容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用与模式空间剩余的内容。
      这三个命令能建立一个输入、输出循环,用来维护两行模式空间,但是一次只输出一行。
      这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。
       
       删除文件倒数第二行
       sed 'N;$!P;D' a.txt
       删除文件最后两行
       sed 'N;$!P;$!D;$d' a.txt

#练习:
    ```
将第一行插入到每个偶数行的后面
    
    $ sed  '1h;0~2G' a.txt
    11111111
    22222222
    11111111
    33333333
    44444444
    11111111
    55555555
    66666666
    11111111
    
    
    颠倒输出
    $ sed '1!G;h;$!d' rev.txt
    xyz
    def
    abc
    $

大写转换
样本文件 a.txt
find the Match statement
Consult the Get statement.
using the Read statement to retrieve data
将 the 和statement之间的单词转换成大写
脚本:changsrc
# capitalize statement names
/the .* statement/{
h
s/.*the \(.*\) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/\(.*\)\n\(.*the \).*\( statement.*\)/\2\1\3/
}


脚本方法
     -f 参数 引用脚本(脚本的末尾不能有空格制表符或其他文本)
    # cat sed.sh 
    2,4d
    s/777/seker/
    s/999/seker&seker/
    # sed -f sed.sh test.txt 
    1111111
    5555555
    6666666
    seker7777
    8888888
    seker999seker9999
    #

  在脚本中指明解释器为sed
    # cat sed.sh 
    #!/bin/sed -f
    2,4d
    s/777/seker/
    s/999/seker&seker/
    # ./sed.sh test.txt 
    1111111
    5555555
    6666666
    seker7777
    8888888
    seker999seker9999
    # 

高级流控命令 b分支 t测试
    分支命令用于无条件转移,测试命令用于有条件转移

分支 branch
   跳转的位置与标签相关联
    如果有标签则跳转到标签所在的后面行继续执行
    如果没有标签则跳转到脚本的结尾处.
   标签 以冒号开始后接标签名 不要在标签名前后使用空格

跳转到标签指定位置
[root@stu254 ~]# grep seker /etc/passwd
seker:x:500:500::/home/seker:/bin/bash
[root@stu254 ~]#
[root@stu254 ~]# grep seker /etc/passwd |sed ':top;s/seker/blues/;/seker/b top;s/5/555/' 
blues:x:55500:500::/home/blues:/bin/bash
[root@stu254 ~]# 

命令分析:让单次替换(cmd1)循环执行,直到条件不满足
:top; 定义一个top标签
s/seker/blues/; cmd1
/seker/b top; 如果模式匹配则跳转到top标签
s/5/555/ 当上一条模式不匹配时,既会继续执行这一条

选择执行
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash
[root@stu254 ~]# 

zorro:x:501:501::/home/zorro:/bin/bash
[root@stu254 ~]#  grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
zorro:x:6665501:501::/home/zorro:/bin/bash
[root@stu254 ~]# 

命令分析: 执行cmd1,再去模式匹配,成功则跳转到cmd3开始执行,否则(模式不匹配)会按命令顺序逐个执行
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
:end;
s/5/666/ cmd3

另一种选择执行
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash

[root@stu254 ~]#  grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
zorro:x:55501:501::/home/zorro:/bin/bash
[root@stu254 ~]# 

命令分析: 执行cmd1;模式匹配cmd2成功则执行cmd3;否则执行cmd2,再跳转到脚本末尾 
s/seker/blues/; cmd1
/seker/b end;
s/5/555/;  cmd2
b;
:end;
s/5/666/ cmd3

测试命令,如果前一个替换命令执行成功则跳转到脚本末尾 (case结构)
[root@stu254 ~]  grep 'seker' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/bash

[root@stu254 ~]  grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash
[root@stu254 ~]

与标签关联,跳转到标签位置
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/XYZ

你可能感兴趣的:(模式空间与保持空间)