如果一行匹配条件,sed 将替换与模式范围匹配的行
sed to replace lines matched by a pattern range if one line match a condition
我需要删除以下示例文件格式的记录:
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尝试
##########################
使用 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`
谢谢。
你可以试试:
$ 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
相信这可以满足您的需求,但它会在前面加上一个空行。它只是将它们作为段落括起来,然后删除具有该记录名称的那个。
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'
这可能适合您 (GNU sed):
sed -E '/record \{/{:a;N;/\}/!ba;/my_id_2/!b;s/(record \{.*).*//;t;d}' file
使用您原来的方法,但使用贪婪进行额外的测试,如果成功则保留匹配字符串的前面。如果没有这样的匹配项,则还原并像以前一样删除整个匹配字符串。
N.B。这可能会引入一些不需要的填充,将其删除留作 reader ;-)
的练习
我需要删除以下示例文件格式的记录:
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尝试
##########################
使用 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`
谢谢。
你可以试试:
$ 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
相信这可以满足您的需求,但它会在前面加上一个空行。它只是将它们作为段落括起来,然后删除具有该记录名称的那个。
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'
这可能适合您 (GNU sed):
sed -E '/record \{/{:a;N;/\}/!ba;/my_id_2/!b;s/(record \{.*).*//;t;d}' file
使用您原来的方法,但使用贪婪进行额外的测试,如果成功则保留匹配字符串的前面。如果没有这样的匹配项,则还原并像以前一样删除整个匹配字符串。
N.B。这可能会引入一些不需要的填充,将其删除留作 reader ;-)
的练习