catalyst_list has asked for the wisdom of the Perl Monks concerning the following question:

Hello All, I have a file that has the following array format from a nagios .cfg file.

define service { host_name kr-cont00 service_description PING check_command check_host max_check_attempts 1 check_interval 1 retry_interval 2 check_period 24x7 check_freshness 1 contact_groups admins notification_interval 60 notification_period 24x7 notifications_enabled 1 register 1 } define service { host_name KT service_description Check SSH check_command check_ssh max_check_attempts 1 check_interval 1 retry_interval 2 check_period 24x7 check_freshness 1 contact_groups admins notification_interval 60 notification_period 24x7 notifications_enabled 1 register 1 } define service { host_name KT service_description Controller Load check_command check_nrpe!check_load max_check_attempts 1 check_interval 1 retry_interval 2 check_period 24x7 check_freshness 1 contact_groups admins notification_interval 60 notification_period 24x7 notifications_enabled 1 register 1 }

I have a lot of this files that I need to modify the contact_groups for certain services (for example the define service for PING should be skipped). Below is the code below:

#!/usr/bin/perl $input_file="kt.txt"; open FT, "$input_file"; @input = <FT>; close FT; $check = "check_nrpe"; $con = "contact_groups"; foreach $list (@input) { if ($list =~ /PING/) { next; } if ($list =~ /$check/ && $list =~ /$con/) { print "$list\n"; } }

I get no output when I run the script. but if I use the || instead of &&, the output I get contains contact_group output from PING which does not require modification. Thank you for your envisaged response.

Replies are listed 'Best First'.
Re: && comparison not working
by NetWallah (Canon) on Mar 02, 2019 at 05:42 UTC
    Taking a guess at what you are trying to do .. this code may help:
    #!/usr/bin/perl use strict; use warnings; local $/="}"; # So we can slurp an entire service in one read my $host_txt= "host_name"; my $check = "check_nrpe"; my $con = "contact_groups"; while (my $list = <DATA>){ next if $list=~/PING/; # UPDATE: O.P. Added this sample after I po +sted next unless $list=~ m/$host_txt\s+(\w+).+$check.+$con\s+(\w+)/so; print "GROUP NAME: $2; for host $1\n"; } __DATA__ define service { host_name KT service_description Check SSH check_command check_ssh max_check_attempts 1 check_interval 1 retry_interval 2 check_period 24x7 check_freshness 1 contact_groups admins notification_interval 60 notification_period 24x7 notifications_enabled 1 register 1 } define service { host_name KT service_description Controller Load check_command check_nrpe!check_load max_check_attempts 1 check_interval 1 retry_interval 2 check_period 24x7 check_freshness 1 contact_groups admins notification_interval 60 notification_period 24x7 notifications_enabled 1 register 1 }
    OUTPUT:
    GROUP NAME: admins; for host KT

                    As a computer, I find your faith in technology amusing.

Re: && comparison not working (updated)
by AnomalousMonk (Archbishop) on Mar 02, 2019 at 04:56 UTC
    .. if I use the || instead of &&, the output I get contains contact_group output from PING ...

    This doesn't seem possible to me: given the code you posted, no @input line with a 'PING' substring will be processed further. The && (logical and) of regex matches works for me as I expect:

    c:\@Work\Perl\monks>perl -wMstrict -le "my @input = ( 'PING foo wrong', 'PING check_nrpe wrong', 'PING contact_groups wrong', 'PING check_nrpe contact_groups wrong', 'PING contact_groups check_nrpe wrong', 'foo wrong', 'check_nrpe wrong', 'contact_groups wrong', 'check_nrpe contact_groups BINGO!', 'contact_groups check_nrpe BINGO!', ); ;; my $check = 'check_nrpe'; my $con = 'contact_groups'; ;; for my $list (@input) { next if $list =~ /PING/; ;; print qq{'$list'} if $list =~ /$check/ && $list =~ /$con/; } " 'check_nrpe contact_groups BINGO!' 'contact_groups check_nrpe BINGO!'

    Update: Be aware that you are processing the example file on a line-by-line basis (update: with the code you've posted), not on a  define service { ... } block basis.


    Give a man a fish:  <%-{-{-{-<

Re: && comparison not working
by hippo (Archbishop) on Mar 02, 2019 at 09:42 UTC
    if ($list =~ /$check/ && $list =~ /$con/) {

    This condition will never be true because there is no line in your input file which matches both regular expressions.

      Depends on how you define 'line', and regex options used. See my (working) solution above.

                      As a computer, I find your faith in technology amusing.

Re: && comparison not working
by AnomalousMonk (Archbishop) on Mar 02, 2019 at 07:32 UTC

    Here's another guess at what you might want. Uses OPed example input file and hard-coded file name. Warning: Not extensively tested. (This runs under Perl version 5.8.9.)

    File edit_nagios_cfg_2.pl:

    Output:


    Give a man a fish:  <%-{-{-{-<