如何使用 sed 更改特定组中的单词?

如何使用 sed 更改特定组中的单词?

我需要更改特定define service部分中的一个单词 where service_descriptionisNRPE - NTP_TIME和 where contact_groupsis opsgenie-sla1,我需要更改为opsgenie-sla2并且我想使用sed命令来缩短我的工作,因为我需要在多个主机上执行此操作。以下是该文件的片段;例如

define service{
        use                             generic-service

        service_description             NRPE
        is_volatile                     0
        check_period                    24x7
        max_check_attempts              3
        check_interval           5
        retry_interval            2
        contact_groups                  opsgenie-sla1

        notification_period             24x7
        check_command                   check_nrpe_port_ssl
        }

    define service{
        use                             generic-service
        host_name                       dns1
        service_description             NRPE - NTP_TIME
        servicegroups                   ntp_checks
        is_volatile                     0
        check_period                    24x7
        max_check_attempts              3
        check_interval           5
        retry_interval            2
        contact_groups                  opsgenie-sla1


        check_command                   check_custom_nrpe!check_ntp_time
        }

答案1

使用,假设这些服务内perl没有其他{s, s ,您可以执行以下操作:}{...}

perl -0777 -pi -e '
  s{^\h*define\h+service\s*\{.*?\}}{
    my $service = $&;
    if ($service =~ m{^\h*service_description\h+NRPE - NTP_TIME\h*$}m) {
      $service =~ s{^\h*contact_groups\h+opsgenie-sla\K1\h*$}{2}gm;
    }
    $service;
  }mges' -- your-file

perl -pperlsed模式。使用-0777,我们将记录分隔符定义为不可能的事情,因此唯一的记录是完整的文件。

然后我们使用常见技术应用替换:在模式中,匹配整个define service {...},并且替换被解释为代码(感谢标志e),这是仅当匹配具有正确的 时才替换联系人组的匹配service_description

的替换contact_groups为:

s{^\h*contact_groups\h+opsgenie-sla\K1\h*$}{2}gm

此处将 替换1<horizontal-spacing-if-any>2

改成:

s{^\h*contact_groups\h+\K.*}{opsgenie-sla2}gm

例如,无论它们之前是什么,都将contact_groups其更改为。opsgenie-sla2

或者:

s{^\h*contact_groups\h+(.*,\h*)?opsgenie-sla\K1(?=\h*,|\h*$)}{2}gm

要将其更改12in opsgenie-sla1that,前面或后面可能有更多以逗号分隔的单词。

或者:

s{^\h*contact_groups\h+(.*,\h*)?\Kopsgenie-sla1(?=\h*,|\h*$)}{opsgenie-sla2}gm

来替换整个单词。\K标记K匹配中的 ept ( $&),(?=...)是一个前瞻运算符,它找到的内容不包含在匹配中。

您可以使用 来了解这些s{regexp}{replacement}flags m{regexp}flags运算符perldoc -f sperldoc -f m并使用 来了解正则表达式语法perldoc perlreperldoc perlsyn关于调用和选项的语法perldoc perlrun,或者从 开始整个旅程perldoc perl

答案2

这是使用 GNU 的解决方案sed,但是您将丢失文件的正确缩进,最好使用 Stéphane 提供的解决方案:

sed ':a;N;$!ba;s/\n/ /g' <filename> | sed 's/\(define service{.*service_description\s*NRPE - NTP_TIME.*contact_groups\s.*\)opsgenie-sla1/\1opsgenie-sla2/g'

答案3

使用任何 POSIX awk:

$ cat tst.awk
/define service.*\{/ { prt(); numLines=0 }
{
    lines[++numLines] = $0
    tag = $1
    gsub(/^[[:space:]]*[^[:space:]]+[[:space:]]*|[[:space:]]+$/,"")
    tag2lineNr[tag] = numLines
    tag2val[tag] = $0
}
END { prt() }

function prt(   lineNr) {
    if ( tag2val["service_description"] == "NRPE - NTP_TIME" ) {
        lineNr = tag2lineNr["contact_groups"]
        sub(/opsgenie-sla1/,"opsgenie-sla2",lines[lineNr])
    }
    for ( lineNr=1; lineNr<=numLines; lineNr++ ) {
        print lines[lineNr]
    }
}

$ awk -f tst.awk file
define service{
        use                             generic-service

        service_description             NRPE
        is_volatile                     0
        check_period                    24x7
        max_check_attempts              3
        check_interval           5
        retry_interval            2
        contact_groups                  opsgenie-sla1

        notification_period             24x7
        check_command                   check_nrpe_port_ssl
        }

    define service{
        use                             generic-service
        host_name                       dns1
        service_description             NRPE - NTP_TIME
        servicegroups                   ntp_checks
        is_volatile                     0
        check_period                    24x7
        max_check_attempts              3
        check_interval           5
        retry_interval            2
        contact_groups                  opsgenie-sla2


        check_command                   check_custom_nrpe!check_ntp_time
        }

相关内容