sed 记录总结

sed总结
这篇博文是在阅读sed&awk第二版这本书做的记录,仅作为以后备忘使用.有些仅仅是自己的理解,不保证绝对正确.本文假设读者已经掌握基本的正则表达式
    1. 名词解释

      模式空间:sed维护的一个缓冲区,脚本或命令都是直接作用与这个缓冲区.按照sed的工作方式分类,模式空间还分为单行模式空间及多行模式空间.
      保持空间:也是一个缓冲区,他可以与模式空间交换数据.

    2. sed入门
      sed基本语法:
      [address]command
      基本上sed语法都是在地址后面跟命令.有些命令只接受单地址,但是有些命令接受一个范围的地址.
      地址可以用正则表达式匹配(/^$/d),也可以用行号表示(1,5d),甚至可以用特殊标记(1,$d)($在这里表示最后一行).
      花括号可以在同一个地址上执行多条命令,形如
      address{
      command1
      command2
      command3
      }
      花括号是可以嵌套在一个地址中,也即是在一个范围里面进行一些操作.例如:/#ifdef DEBUG/,/#endif/{
      /^$/d
      }
      删除上述范围的所有空行
      ! 表示不对某一个地址执行某执行,比如 $!n表示不在处理文本的最后一行执行n操作.这里的$表示处理文本的最后一行(通常是文件)

      常用的命令介绍:
      替换    s
      [address]s/pattern/replacement/flage
      flage选项

      n,它的取值是1到512.意味对模式的第n次匹配进行替换
      g,它意味对所有匹配到的模式均进行替换.如果不添加这个选项,它将只替换第一次匹配
      p,打印模式空间的内容
      W file,将模式空间的内容写入到文件file

      flage是可以组合使用的只要它有意义,

      replacement部分(&)号表示正则表达式匹配的值,(\n)表示第n个匹配的子串.其中0子串表示整个匹配到的子串.与标记(&)相当
      地址需要(/)作为定界符,而正则表示式可以使用任何符号作界定符.例如:s!/usr/bin!/usr2/bin!

      删除    d
      它可以作用于一个地址和一个范围,例如:sed '1,$d' test1将删除从第一行到最后一行的所有内容.


      插入,更改,追加
      [line-address]i\
      text
      [address]c\
      text
      [line-address]a\
      text
      上诉三条语法更改可以应用在一个范围,而其余两条都只应用于一个地址.插入对应在模式空间所对应当前行的前面,改变对应当前行,追加对应后面.插入和追加不影响模式空间的内容,新加的内容不会匹配后面的脚本

      列表 l
      输出模式空间的内容

      转换 [address]y/abc/xyz
      它将地址匹配的行中出现的a换成x,出现的b换成y,依次类推

      打印 p
      打印模式空间的内容

      打印行号 =
      [address]=

      读新的一行 n
      它是单行模式空间的命令,它读一行数据覆盖模式空间.但不改变执行流程.(sed&awk)相关部分写的晦涩难懂,坑啊

    3. sed进阶
      多行模式空间
      N,D,P
      N是多行模式空间的n,它将新的一行追加到模式空间的尾上,在原来的行尾增加标记'\n'符.
      D是多行模式空间的d,它只删除模式空间的开始到第一个'\n'的位置的文本
      P是多行模式空间的p,它只打印模式空间的开始带第一个'\n'的位置的文本

      保持空间
      h,H 他们分别表示将模式空间的内容复制到报纸空间和追加到保持空间.操作完成之后追加一个换行符
      g,G 他们分别表示将保持空间的内容复制到模式空间和追加到模式空间.在操作之前先写入一个换行符
      x 交换保持空间和模式空间的数据

      无条件跳转
      [address]b label
      在替换命令之后可以使用有条件跳转,仅在操作成功时才跳转
      [address]t label
      定义一个标签
      : label

    4. 关于控制流的问题
      这是一个非常容易造成迷惑的地方,以下详细分析一下n,N,d,D的异同,不知是理解的问题还是其他问题.对于书的描述越看越迷惑.以下根据我的疑问作出实验得出答案.
      • 使用n命令之前模式空间的变化,以及控制流的走向?(p命令不改变模式空间内容及控制走向)

                                                         图1

                                                         图2
        分析:图1说明3行文本都匹配到正则表达式里面.图2显示出了3行文本,第一条显示是第一个l命令显示的,接着执行了n命令,接着执行p命令显示了第二条,然后控制返回了顶端,脚本携带第三条记录被显示出来,到n的时候已文件已结束
        结论:n命令不改变执行流程,只是用新的东西覆盖原有的东西.但是sed&awk第二版书相关章节说控制返回脚本顶端实在是理解不了.若控制返回了顶端第二条记录尾上应该还有个$符
      • 使用N命令之前模式空间的变化以及控制流的走向?

                                                        图3

                                                       图4
        分析:图3第一行显示是脚本中的l显示的,第二行和第三行是N命令之后p输出的.最后一个记录是第二次脚本执行l输出的.图4第一行是l显示的,第二行是第二个l显示的,第三行是第二次执行脚本的时候第一个l显示的
        结论:N只是向原有模式空间追加换行和新一行的内容.不改变控制流走向.
      • 使用d命令之前模式的模式空间的变化以及控制流走向.

                                                       图5
        分析:若控制流不返回脚本顶端,第一个l会输出图中的第一个记录,d后面的命令会执行.也就是说最后会生成3条记录.实际上只有两条记录.
        总结:d命令会清空模式空间所有内容并且控制会返回脚本顶端.它还会自动向模式空间载入新的内容.
      • 假设D命令只删除第一行且控制直接跳转到脚本顶端,但是不会主动向模式空间载入新的内容,且不重置模式空间的内容.

        结论:D命令之后控制直接返回至脚本顶端,原模式空间的内容不重置.若D之后模式空间为空,sed自动读下一行重复执行脚本.


    5. 最后,对sed作以下总结:
      • sed的内部计数器(行号)只增加不减少,而增加的方法有两种,模式空间在命令d或D清空的时候,sed会自动读新的一行进来从而增加内部计数器,第二种是在n或N的作用下.内部计数器的值始终和模式空间最后一行所对应的行号一致.
      • D或d命令操作之后,控制流;立即回到脚本顶端.也就是说他们后面的代码不会执行,如果D命令之后模式空间不为空,模式空间的内部不会重置.
      • 在某一个地址上应用多条命令,也就是在某一个地址后面用花括号执行多条命令.执行的命令D或d,控制会回到脚本顶端,
    6. 最终,根据我的理解如果我要自己实现一个sed我会这样做
      • 定义基本数据结构
        定义处理文本的内部计数器也即行号,定义缓冲区1(模式空间),定义缓冲区2(保持空间),
      • 定义一组用户可操作的命令接口
        l   输出缓冲区1(模式空间)的所有字符,不删除末尾的$符
        p 打印缓冲区1(模式空间)的所有内容,直接删除缓冲区末尾的$符后用C语言的snprintf,也就是说换行符也会输出
        n 从处理文本中取新的一行数据覆盖缓冲区1(模式空间),内部计数器加1
        d 清空模式空间的所有数据,控制转入脚本的第一行(不是处理文本)
        N 在模式空间替换末尾的$符为换行符追加新一行的内容后再在新内容追加一个$符,内部计数器+1
        P 显示从首行开始一直到第一个嵌入的换行符的所有内容
        D 删除从首行开始一直到第一个嵌入的换行符的所有内容,控制转入脚本的第一行
        i,c,a 插入,改变,追加没啥特殊的地方,他们不会引起内部计数器的变化.也就是说你插入了追加了新内容,它不会被接下来的处理流程命中.他们分别作用域当前处理行的前一行,当前处理行,当前处理行后一行
        s 替换,可选的地址范围限定,替换....,也没啥可特别注意的地方.有条件的跳转指定t作用与替换操作之后
        b 可选的地址限定,跳转到脚本的某一行
        t 可选的地址选项,上一条替换操作成功才执行跳转
        : 声明一个标签
        g,G 从缓冲区2(保持空间)复制或追加数据到缓冲区1(模式空间),追加(复制不算)之前先向模式空间追加一个换行符
        h,H 从缓冲区1(模式空间)复制或追加数据到缓冲区2(保持空间),,追加(复制不算)之前先向保持空间追加一个换行符
        x 交换两个缓冲区的数据
        q 退出处理流程
      • sed代码操作流程
        1. 初始化sed内部数据结构(内部计数器等)
        2. 处理文本已经处理完,执行命令q退出处理流程
        3. 如果模式空间为空,sed自动执行命令n
        4. 执行用户的脚本
          • 若用户的命令中未出现D或d命令,用户代码执行完成后跳转到过程2
          • 若用户的命令脚本中出现D或d命令,D或d操作执行后直接跳转到过程2.D或d后面的代码将没有机会执行
          • 若用户的命令出现了b或t(无)条件跳转指令,执行流程将跳转到用户代码的某一行(用户指定的)
          • 其余的命令都是顺序执行
      • 注意,内部计数器与模式空间的最后一行数据所对应的当前行的行号一致.也就是说即使是多行模式下,执行D命令之后,控制返回到上面的过程2.由于模式空间不为空,sed不自动执行n命令.所以,内部计数器不变.换句话说,在控制返回之前和返回之后内部计数器都不变.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值