파일에 string1이 존재할 때 string2를 찾습니다.

파일에 string1이 존재할 때 string2를 찾습니다.

다음 구조의 구성 파일(Nagios)이 있습니다.

define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server1.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  JUVEPoolDSPoolDS
    check_command           check_ds_oas!cfio!JUVEPoolDSPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server1.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  REMEPoolDS
    check_command           check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  iris_usr_irisPoolDS
    check_command           check_ds_oas!cfio!iris_usr_irisPoolDS!/opt/oracle/ias10g/10.1.3!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  REMEPoolDS
    check_command           check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}

define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  redt2_usr_redt2PoolDS
    check_command           check_ds_oas!cfio!redt2_usr_redt2PoolDS!/opt/oracle/ias10g/10.1.3!1!0
}

check_command이 파일에 새 서비스를 등록하려면 먼저 서비스가 존재하는지 확인해야 하며, 이를 위해서는 서비스가 host_name등록되지 않았는지 확인해야 합니다 .

예를 들어, 다음을 등록하고 싶습니다.

define service {
     use pre-service tests, srv-pnp
     host_name server1.es
     servicegroups testsdatasourcesoaspre-servicegroup, pre-servicegroup tests
     service_description DataSource Status - cfio REMEPoolDS
     check_command check_ds_oas! cfio! REMEPoolDS! /opt/oracle/ias10g/10.1.2! 1! 0
}

그래서 내가 찾아야 할 파일에는 존재하지 않습니다.

while 루프를 사용하여 파일을 읽으려고 시도했는데 발견되었을 때

check_command check_ds_oas! Cfio! REMEPoolDS! /Opt/oracle/ias10g/10.1.2! 1! 0

다음은 아닌 것 같아

host_name server1.es
V_NAGIOS_COMMAND=check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
if [ `grep ${V_NAGIOS_COMMAND} --count $V_FILE_NAGIOS` -ge 1 ] ; then
    while read LINEA_CONFIG
    do
        V_DIRECTIVA=`echo $LINEA_CONFIG| awk '{print $1} '`
        V_VALOR_DIRECTIVA=`echo $LINEA_CONFIG| awk '{print $2} '`
        if [ $V_DIRECTIVA = check_command ]&&[ $V_VALOR_DIRECTIVA = $V_NAGIOS_COMMAND ]; then
            V_COMANDO_ENCONTRADO=1
        elif [ $V_DIRECTIVA = host_name ]&& [ $V_COMANDO_ENCONTRADO = 1 ] ; then
            if [ $V_VALOR_DIRECTIVA = $V_MAQUINA ] ; then
                ((V_EXISTEN_DATOS++))
                return 1
            else
                V_COMANDO_ENCONTRADO=0
            fi
        fi
    done < <(tac $V_FILE_NAGIOS| grep -vE "^#|^$")
fi

하지만 느립니다.

답변1

귀하의 요구 사항을 잘 이해한다면 sed입력 스트림 내에서 "하위 스트림"을 분리할 수 있으므로 이 작업을 잘 수행할 수 있는 것처럼 보입니다.

POSIX여야 합니다.

sed -n "/^define service/,/^}/{/^[[:blank:]]\\{1,\}host_name[[:blank:]]\\{1,\\}${V_MAQUINA}/,/^}/{\\%^[[:blank:]]\\{1,\\}check_command[[:blank:]]\\{1,\\}${V_NAGIOS_COMMAND}%{p;q}}}" file

또는 GNU sed를 사용할 수 있는 경우 문자열의 이스케이프를 줄일 수 있습니다.

sed -En "/^define service/,/^\\}/{/^[[:blank:]]+host_name[[:blank:]]+${V_MAQUINA}/,/^\\}/{\\%^[[:blank:]]+check_command[[:blank:]]+${V_NAGIOS_COMMAND}%{p;q}}}" file

설명하다:

sed -En  # use Extended Regular Expressions, and don't print by default

# main `sed` script for entire stream
/^define service/,/^\\}/  # between 'define service' and '}'
{  # sub-stream: between specified 'host_name' and '}'
/^[[:blank:]]+host_name[[:blank:]]+${V_MAQUINA}/,/^\\}/
{  # look for specified 'check_command', using '%' because '/' can be in command
\\%^[[:blank:]]+check_command[[:blank:]]+${V_NAGIOS_COMMAND}%
{p;q}  # if found, print line and quit `sed`
}
}

check_command정규식으로 구분된 "스니펫"에서 행이 발견되면 해당 행을 인쇄하고 file, 그렇지 않으면 아무것도 인쇄하지 않습니다.

따라서 반환된 문자열이 존재하는지 확인하면 됩니다.

sed 아무것도 인쇄되지 않을 때도 0으로 종료되므로 종료 상태를 확인하지 않습니다 .

몇 가지 추가 참고 사항:

  • 쉘에서 큰따옴표 안에 있기 때문에 \\1을 표현 해야 합니다 .\
  • $V_MAQUINA쉘 변수를 사용하려면 큰따옴표를 사용합니다.$V_NAGIOS_COMMAND
  • %이전 정규식에서 정규식 구분 기호로 선택했지만 변수 에 표시되지 않는 문자를 자유롭게 선택할 수 있습니다.$V_NAGIOS_COMMAND

답변2

전혀:

/^define service/{

    found_command=0
    found_host=0

    while (getline && $0 !~ "^}") {

        # test host
        if($1 == "host_name") {
            if ($2 == new_host) {
                found_host=1
            }else{
                next
            }
        }

        # test check_command
        if($1 == "check_command"){
            cmd = gensub(/^\s*check_command\s*/, "", 1)
            if (cmd == new_command) {
                found_command=1
            }else{
                next
            }
        }
    }

    if (found_command && found_host)
        exit 1
}

다음과 같이 사용할 수 있습니다.

new_host='...'
new_command='...'
if awk -v new_host="$new_host" -v new_command="$new_command" -f script.awk cfg_file ; then
    echo "you can register it now"
fi

관련 정보