【问题标题】:sed to replace lines matched by a pattern range if one line match a condition如果一行匹配条件,则 sed 替换与模式范围匹配的行
【发布时间】:2021-03-15 23:18:27
【问题描述】:

我需要删除以下示例文件格式的记录:

record {
    record {
        my_id_1
        my_name_1
    }
    
    record {
        my_id_2
        my_name_2
    }
    
    record {
        my_id_3
        my_name_3
    }
}

在这种情况下,我们需要使用唯一值 my_idmy_id_2 删除所有记录数据,预期结果应该是:

record {
    record {
        my_id_1
        my_name_1
    }
    
    record {
        my_id_3
        my_name_3
    }
}

注意:该文件不是一个标准的谈论空格,换行等。但核心逻辑可能是删除单词record[包括相同单词]之间的所有内容,仅与my_id_*字符串相关在括号中。

到目前为止,我所能做的就是写:

sed -n '/record/{:a;N;/}/!ba; /my_id_2/p}' file.conf

事实上,它找到了我需要的东西,但我无法删除它我只打印我想要清除的行。

sed 是我的主要选择,但 python regex 也可以,因此我可以将其传递给 ansible。

##########################

这也是我的 Python 尝试

##########################

工具:https://pythex.org/

使用 python 这是我得到的最接近的:

第一次尝试: (?=my_id_2)([^}]+)(?=\})

有匹配结果:

    `my_id_2 my_name_2`

然后稍作修改: (?=record )([^}]+)(?=\})

有匹配结果:

Match 1

    `1. record { record { my_id_1 my_name_1`

Match 2

    `1. record { my_id_2 my_name_2`

Match 3

`1. record { my_id_3 my_name_3`

谢谢。

【问题讨论】:

  • 使用 python 这是我得到的最接近的:第一次尝试:(?=my_id_2)([^}]+)(?=\}) 匹配结果:my_id_2 my_name_2 然后修改了一下:(?=record )([^}]+)(?=\}) 匹配结果:Match 11. record { record { my_id_1 my_name_1@987654346 @1. record { my_id_2 my_name_2Match 31. record { my_id_3 my_name_3

标签: python regex linux sed scripting


【解决方案1】:

你可以试试:

$ sed -i.bak '/record/{:a;N;/}/!ba; /my_id_2/d}' file.conf
$ cat file.conf
record {
    record {
        my_id_1
        my_name_1
    }
    
    
    record {
        my_id_3
        my_name_3
    }
}

以上内容就地修改文件并创建文件的备份,命名为file.conf.bak。如果您不需要原始文件的备份,您可以从-i.bak 中删除.bak

【讨论】:

    【解决方案2】:

    相信这可以满足您的要求,但它会在前面添加一个空行。它只是将它们作为段落括起来,然后删除具有该记录名称的段落。

    sed '/./{H;$!d} ;x; /my_id_2/d' file.conf
    

    您可能认为可以在 sed 语句后附加一个额外的 ; 1d 来删除它。

    sed '/./{H;$!d} ;x; /my_id_2/d ; 1d' file.conf
    

    但是,这没有任何效果,并且第 1 行仍然是空白的。您可以通过将其传递给后续的sed 命令来克服这个问题,但这似乎很不稳定。也许其他人知道原因。

    sed '/./{H;$!d} ;x; /my_id_2/d' file.conf | sed '1d'
    

    https://www.gnu.org/software/sed/manual/sed.html

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -E '/record \{/{:a;N;/\}/!ba;/my_id_2/!b;s/(record \{.*)\1.*/\1/;t;d}' file
      

      使用您的原始方法,但使用贪婪进行额外测试,如果成功,则保留匹配字符串的前面。如果没有这样的匹配,恢复并像以前一样删除整个匹配的字符串。

      注意这可能会引入一些不需要的填充,将其删除作为练习留给读者;-)

      【讨论】:

        猜你喜欢
        • 2016-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-08
        • 2018-02-24
        • 2021-04-15
        • 2021-11-18
        相关资源
        最近更新 更多