如果一行匹配条件,则 sed 替换与模式范围匹配的行
Posted
技术标签:
【中文标题】如果一行匹配条件,则 sed 替换与模式范围匹配的行【英文标题】:sed to replace lines matched by a pattern range if one line match a condition 【发布时间】: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_id
或 my_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 1
1. record record my_id_1 my_name_1
@987654346 @1. record my_id_2 my_name_2
Match 3
1. record my_id_3 my_name_3
【参考方案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
使用您的原始方法,但使用贪婪进行额外测试,如果成功,则保留匹配字符串的前面。如果没有这样的匹配,恢复并像以前一样删除整个匹配的字符串。
注意这可能会引入一些不需要的填充,将其删除作为练习留给读者;-)
【讨论】:
以上是关于如果一行匹配条件,则 sed 替换与模式范围匹配的行的主要内容,如果未能解决你的问题,请参考以下文章