使用“sed”或“awk”仅在 2 个不同模式匹配后在文件中查找和替换文本

使用“sed”或“awk”仅在 2 个不同模式匹配后在文件中查找和替换文本

这是此处提出和回答的问题的扩展:使用 sed 在文件中查找并替换模式匹配后的第一次出现的文本

问题是:我需要执行查找和替换,但是仅有的在第一次出现 之后,pattern1接着pattern2。这就是pattern3查找和替换必须发生的地方。

使用链接问题中的示例文件的变体:

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '1234'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

我需要这个:

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '9876'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

前两个Server名称相同。option type每个服务器的 不同。我需要匹配一个特定Server名称 ( Test AB),然后匹配一个option type( sb),然后更改端口号。

我不知道如何使多个模式以逻辑方式连接起来AND

有什么建议吗?sed或者awk解决方案是首选(但对于寻找真实的挑战,尝试使用纯 BASH 替换来完成。BASH 5 及以上版本都可以)。谢谢。

答案1

sed允许您在表单中指定地址范围addr1,addr2。链接的答案使用范围。现在您需要嵌套范围。

sed "
/^Server 'Test AB'$/,/^$/ {
/option type 'sb'/,/option port '/ s/option port '.*'/option port '2222'/
}" file

意思是:从(包括)一行开始Server 'Test AB'到(包括)下一个空行应用里面的代码{}

并且里面的代码的{}意思是:从(包括)包含的行option type 'sb'到(包括)包含option port '应用s/…/…/命令的行。

s/…/…/命令的意思是:在每一行中将第一次出现的option port '.*'.*贪婪匹配零个或多个字符)替换为option port '2222'

笔记:

  • 幸运的是,我们可以使用空行来结束范围。如果没有它们,我们可能会试图指定从 到Server的范围Server。问题是从Server 'Test AB'到 的下一个出现的第一个范围Server将包括 的第二个出现Server 'Test AB';并且 在sed同一段代码检测到的范围addr1,addr2不能重叠。实际上, 的第二个出现不会被视为新范围的开始,因此本节中的行不会执行里面的Server 'Test AB'代码。{}

  • ^$分别是行首和行尾的锚点。我将它们与 一起使用,Server 'Test AB'但我故意没有将它们与 一起使用option type 'sb'。请根据需要调整代码。

  • $我使用双引号是因为数据包含单引号。通常双引号中需要转义,但这里/每个引号后面都有$; ,$/这不是 shell 变量的有效名称,也不是 shell 想要扩展的任何内容,因此无需转义$

相关内容