[Megoldva] string keresése {} között

Van egy szabványosnak mondható nagios config fájlom:

...
define service{
use local-service ; Name of service template to use
host_name db-vas01
service_description Swap Usage
check_command check_local_swap!20!10
}

# Define a service to check SSH on the local machine.
# Disable notifications for this service by default, as not all users may have SSH enabled.

define service{
use local-service-5 ; Name of service template to use
host_name db-vas01
service_description SSH
check_command check_ssh
notifications_enabled 0
}
...

Hogyan kapom meg az SSH service-hez tartozó host_name értékét?
Már az is elég lenne, ha megkapnám a blokkot {-tól }-ig, amiben az SSH szerepel.
Segítene valaki? Lehetőleg sed, vagy awk legyen.
Köszi

Megoldás:
root@db-vas01 ~]# awk 'BEGIN{RS="[{}]" } /SSH/ {for (i=1; i<=NF;i++) {if ($i ~ /host_name/) {print $(i+1)}}}' /opt/nagios/etc/objects/localhost.cfg
db-vas01

Köszönöm mindenkinek a segítséget.
Ha esetleg még lehet valahogy szépíteni a megoldáson, azt szívesen fogadom.

Hozzászólások

A sor alapú eszközök nem a legalkalmasabbak ilyesmire, de azért megoldható.
grep -v "^[[:blank:]]*#" | tr "\n" " " | grep -o "{[^}]*[[:blank:]]service_description[[:blank:]]*SSH[[:blank:]][^}]*}" | sed "s/^.*[[:blank:]]host_name[[:blank:]]*\([^[:blank:]]*\)[[:blank:]].*$/\1/"

awk '/host_name/ {a = $2}; /n SSH/ {print a}' filename

Ez a fajta megoldás miért nem illeszkedik a blokkokra?
awk -F '[{}]' {'print $4'}

Én awk-ban úgy csinálnám, hogy keresném a '{' jelet, ha az megvan, egy flag értéke 1. Ha a flag==1, és illeszkedik a mintára, akkor print. Ha '}', akkor flag=0.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Én ilyen bonyolultságú dolgokkal alapból perlben próbálkozok...

Nem ismerem a nagios-t, de ha nagyon sed/awk, esetleg grep kell, akkor egy olyanból indulnék ki, hogy a define service blokk nem túl rövid, nem túl hosszú (tehát a nyolc sor előtte, nyolc sor utána magába foglalja az egész blokkot, illetve nem fogja az előző ill. következő blokkot teljes egészében magába foglalni):

grep -C 8 "service_description SSH" nagios.conf | sed -n "/define service/,/}/ p" | sed -n "/host_name/ s/host_name \(.*\)/\1/p"

Persze ez általános esetben (pl. rengeteg megjegyzés a fájlban, rövid blokkok, stb.) nem fog működni.

Ilyesmire gondoltam:

#!/usr/bin/awk -f

BEGIN {
    block=0;
    ssh=0;
}

/^[\t ]*#/ {
    next;
}

/^[\t ]*define service[\t ]*{/ {
    ssh=0;
    block=1;
    next;
}

/^[\t ]*}/ {
    if (ssh) {
        print hostname;
    }
    ssh=0;
    block=0;
    next;
}

block {
    if ($0 ~ /host_name/) {
        hostname=$2;
    }
    if ($0 ~ /service_description[\t ]*SSH/) {
        ssh=1;
    }
}

Ebben a blokkon belüli értékadás sorrendje sem számít, mert tárolom a hostnevet, és csak a blokk végén íratom ki, ha az a blokk ssh-ról szólt.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Most nézem, valami nagyon hasonlót zsúfoltál egy sorba. Tudom, gyors voltál, de simán bukhat a dolog azon, hogy nem vizsgálod a comment sorokat, egy kapcsos zárójel bárhol lehet, igyekeztem legalább néhány helyen megengedni a tabulátort, szóközt, de a semmit is.

Szerk.: ha neki a service_description után tabulátor van, a scripted nem veszi észre, amit kell. Nyilván a nem működés oka az lehet, hogy nem jó tesztfile-t kaptunk.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ilyesmire való az awk (sed, perl) tartománymintája:


$ cat szurnivalo.txt
nem kell
nem kell
nem kell
...

innen kell {
   benn 1
   benn 2
   benn 3
} # eddig

nem kell
nem kell
...
$ awk '/^innen kell *{/,/^ *}/' szurnivalo.txt
innen kell {
   benn 1
   benn 2
   benn 3
} # eddig
$

Lehet meg a perlben a nagios objectet hasznalni. (http://search.cpan.org/dist/Nagios-Object/)

Ennek az a elonye hogy a szettagolt config fileket is osszefesuli egy objektumma.

Vegig kell menni a list_servicesen.
Majd az alatti host_name, es a hostgroup_nameken.
Elobbinek van addresse, utobbinak a membersenek van addresse.

Erdemes $Data::Dumper::Maxdepth -et alacsonyra venni. Akkor nem annyira fut el a kepernyod az osszelinkelt objektumjaitol, ha dumpolod a valtozokat.