• sed之h;H和:a;N;ba使用精解(对段落进行操作)


    1)

    文本:
    Handle 0x0058, DMI type 20, 19 bytes
    Memory Device Mapped Address
            Starting Address: 0x0001FFFFC00
            Ending Address: 0x0001FFFFFFF
            Range Size: 1 kB
            Physical Device Handle: 0x0047
            Memory Array Mapped Address Handle: 0x004B
            Partition Row Position: Unknown
            Interleave Position: Unknown
            Interleaved Data Depth: Unknown

    sample 0x0058, DMI type 20, 19 bytes
    Memory Device Mapped Address
            Starting Address: 0x0001FFFFC00
            Ending Address: 0x0001FFFFFFF
            Range Size: 2 kB
            Physical Device Handle: 0x0047
            Memory Array Mapped Address Handle: 0x004B
            Partition Row Position: Unknown
            Interleave Position: Unknown
            Interleaved Data Depth: Unknown

    Handle 0x0058, DMI type 20, 19 bytes
    Memory Device Mapped Address
            Starting Address: 0x0001FFFFC00
            Ending Address: 0x0001FFFFFFF
            Range Size: 3 kB
            Physical Device Handle: 0x0047
            Memory Array Mapped Address Handle: 0x004B
            Partition Row Position: Unknown
            Interleave Position: Unknown
            Interleaved Data Depth: Unknown
    要求:每个段落是Handle开头的就取出Range Size的值:
    1 kB
    3 kB



    1. sed -n '/^Handle/{:a;N;/n$/!{$!ba};s/.*Range Size: ([^n]*).*/1/p}' file
    [解析]
    文本就3个段落,2个空行为分割,用sed首先想到肯定是以空行为分割,把一整段文本读取在一起,然后统一进行匹配和替换,特别注意N读取内容匹配空行是 / $/ ,而不是一般的 /^$/  ,另一个问题是到了尾行因为没有下面的空行来激活,所以我们要在前面加个尾行的匹配跳转。这样就可以成功替换以Handle开头的段落内容,如果没匹配到也当然不会打印。


    1. sed -n 'H;/^$/!{$!b};x;s/nHandle.*Range Size: ([^n]*).*/1/p' file
    [解析]
    因为是以空行为分割,H 追加到 hold space ,后面的替换只对空行或者最后一行才执行,否则都会跳过,也只有符合关键字的才会被替换打印。其他的行则因为 -n 的原因不会被输出。



    最后再附上awk的命令:
    1. awk -vRS= -F" " '/^Handle/{split($5,a,": ");print a[2]}' file



    2)

    文本:
    dn: identifier=1
    objectClass: ZcValidRecord
    DsId: 2
    identifier:2955
    subOptionName: Record
    SvcId: 1
    ZoneId: 0

    dn: identifier=2
    objectClass: ZcValidRecord
    DsId: 2
    identifier:2956
    subOptionName: Record
    SvcId: 2
    ZoneId: 0

    要求后面的数字替换前面的数字:
    dn: identifier=2955
    objectClass: ZcValidRecord
    DsId: 2
    identifier:2955
    subOptionName: Record
    SvcId: 1
    ZoneId: 0

    dn: identifier=2956
    objectClass: ZcValidRecord
    DsId: 2
    identifier:2956
    subOptionName: Record
    SvcId: 2
    ZoneId: 0



    1. sed ':a;N;/n$/!{$!ba};s/([^0-9]*)[0-9]*(.*identifier:)([0-9]*)/1323/' file
    [解析]
    初一看这题觉得不难,就是简单的数字替换,关键就在于数字的位置,我们都知道不管是shell还是awk还是sed,它都是逐行执行的,换句话说,执行到后面的行后,就不可能再对前面的行进行修改,这个跟我们往常的前面匹配修改后面的内容不一样,这里我们利用sed,把内容统一读取后,用正则来匹配修改它。这里还有另外两个要点,第一,文本是以空行为段落分割,在N读取模式中匹配空行不能再是传统的 /^$/ ,而是 / $/ ,这点上特别注意,第二,针对空行触发条件,到了文件末尾时,没有空行来触发,所以要依据文件末行来触发替换,这里就有了两个标签跳转。



    1. sed -n '1h;/^$/!{1!H;$!b};x;s/([^0-9]*)[0-9]*(.*identifier:)([0-9]*)/1323/p' file
    [解析]
    这是 h;H 的搭配;道理也是一样把一个段落读入 hold space 里,再出发条件统一替换。

  • 相关阅读:
    网速成为了工作的瓶颈之一
    项目实施(一)
    一个命运曲折的项目进行曲
    一次小系统的快速开发经历
    项目实施(二)
    进销存系统的成本核算方法一览
    比较2个DataTable中的内容是否相同的方法
    正则表达式 集会
    Url地址重写,利用HttpHander手工编译页面并按需生成静态HTML文件
    定时执行sql存储过程
  • 原文地址:https://www.cnblogs.com/xialiaoliao0911/p/7524031.html
Copyright © 2020-2023  润新知