LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   newbie help with a perl script (https://www.linuxquestions.org/questions/programming-9/newbie-help-with-a-perl-script-627075/)

justinjoseph24 03-10-2008 06:02 PM

newbie help with a perl script
 
Hello,
I'm in need of some help with this script I've written. Any assistance in getting it working would be much appreciated! I want the script to read all filename arguments and do the following to them:

1) Match something in the current file that looks like a website name and store it in a variable. I know there's only one unique website name per file. Should look like $sitename = www.sitename.com
2) Add several lines to the the current file (preferably, but not necessarily, the end-of-file) using regex substitute, including the $sitename var.


Here is the script with comments:
Code:

#!/usr/bin/perl -w
#this script will add action URLs to the nagios config files, right after the first '}' it encounters
use strict;
$^I = ".bak"; #use .bak backup extension
my $sitename; #relative sitename for each file

& get_the_sitename($sitename)
& write_the_action_url()

sub get_the_sitename {                        # loop thru the file and look for something like a sitename, store it in $sitename and end the IF loop if successful
while (<>) {
if (/host_name\s+((?:\w+\.\w+\.\w+))/) {
$sitename = $1;
last if (1==1);
                                }
        }
}

#the problem with the ABOVE block of code is that it writes a blank file, but I only wanted to get the $sitename var to use in the substitution below.

sub write_the_action_url{                #add several new lines to the file using $sitename so new URL additions are relative
while(<>){
if (/}/) {                        #match the first right curly

#use substitute to add all these lines after the first } curly is found. Since There are several } curlys in the file, stop after it finds the first one and makes the substitutions.

  s:(}):}\n\n\#\# BEGIN EXTINFO\ndefine hostextinfo{\n\thost_name\t$sitename\n\taction_url\t$sitename/mrtg\n\ticon_image\torb2.gif\n\ticon_image_alt\tMRTG\n\n}\n\ndefine serviceextinfo{\n\thost_name\t$sitename\n\tservice_description\tServerStatus\n\tnotes\tLinks to ServerStatus page\n\taction_url\t$sitename/xr/status.xml\n\ticon_image\torb1.gif\n\ticon_image_alt\tStatus Page\n}\n\ndefine serviceextinfo{\n\thost_name\t$sitename\n\tservice_description\tHTTP\n\tnotes\t$sitename\n\taction_url\t$sitename\n\ticon_image\thome.gif\n\ticon_image_alt\tHomepage\n}\n\n$1\n\n\#\# END EXTINFO:;
#print $sitename;
        last if (1==1);

        }
  }

}


osor 03-10-2008 06:53 PM

Quote:

Originally Posted by justinjoseph24 (Post 3084409)
Any assistance in getting it working would be much appreciated!

Please format it in a sane manner before expecting assistance. As it is, the script is hard-to-read. And what’s with all the “if(1==1)”s?

justinjoseph24 03-10-2008 07:37 PM

Sorry for the confusion. I've cut out all the non-essentials just to show what I'm trying to do. To reiterate, I just want to batch edit a bunch of files: 1) match the sitename and store it in a variable, then 2) add new lines with the URL provided from $sitename to maintain relativity.


Code:

#!/usr/bin/perl -w
#this script will, for each file, match a sitename www.sitename.com then add a new
#relative URL to the file. Adds the new lines after the first '}' it matches.
use strict;
$^I = ".bak"; #use .bak backup extension
my $sitename; #relative sitename for each file

& get_the_sitename($sitename)
& write_the_action_url()

sub get_the_sitename {                        # loop thru the file and look for something like a sitename, store it in $sitename and end the IF loop if successful
while (<>) {
if (/host_name\s+((?:\w+\.\w+\.\w+))/) { #match "host_name www.sitename.com"
$sitename = $1;            # put the results of the match in $sitename
last if (1==1);            # there are multiple instances of www.sitename.com in the file, so stop the loop after the first one is encountered, then proceed.
                                }
        }
}

#the problem with the ABOVE block of code is that it writes a blank file, but I only wanted to get the $sitename var to use in the substitution below.

sub write_the_action_url{                #add several new lines to the file using $sitename so new URL additions are relative
while(<>){
if (/}/) {                        #match the first right curly

#use substitute to add all these lines after the first } curly is found. Since There are several } curlys in the file, stop after it finds the first one and makes the substitutions.

  s/}/}\nline1\t$sitename\nline2\t$sitename/    #after the first curly, add a few lines of text with the contents of $sitename from the previous loop.
        last if (1==1);                        #there are muliple } curly files, so end the script after this to keep from adding redundant information.

        }
  }

}


osor 03-10-2008 09:38 PM

How about this:
Code:

#!/usr/bin/perl -w
use strict;

$^I=".bak";
undef $/;

while(<>) {
        my ($sitename) = /host_name\s+(\w+\.\w+\.\w+)/;
        s/}/}\nline1\t$sitename\nline2\t$sitename/;
        print;
}


chrism01 03-11-2008 02:09 AM

Don't use '&' to call a sub.
(there are occasional reasons to do so, eg passing a a reference to a sub, but they don't apply here)

justinjoseph24 03-11-2008 02:42 AM

Quote:

Originally Posted by osor (Post 3084551)
How about this:

Yes, I just have to say thank you very much. That is much more eloquent form and worked great. undef $/ to change the read var method was what I needed.

Regards,

-J

osor 03-11-2008 12:44 PM

Quote:

Originally Posted by osor (Post 3084446)
Please format it in a sane manner

Quote:

Originally Posted by justinjoseph24 (Post 3084719)
That is much more eloquent form

I think it would be beneficial if you took a look at
Code:

perldoc perlstyle
A few other remarks about your initial attempt:
  • Notice that
    Code:

    if(1==1)
    always evaluates to true, so it is unnecessary. So you could replace all instances of
    Code:

    last if (1==1);
    with
    Code:

    last;
  • The capturing regular expression
    Code:

    ((?:\w+\.\w+\.\w+))
    may be reduced to
    Code:

    (\w+\.\w+\.\w+)
    since you don’t make any use of the non-capturing properties of (?:…).
  • As chrism01 points out, you can call a subroutine by its name without the & prefix.
  • To make your code clearer, you should keep $line1 and $line2 as variables instead of inlining them as you did in initial attempt.

justinjoseph24 03-12-2008 05:45 PM

tyvm for the critique.

chrism01 03-12-2008 05:49 PM

BTW, if you haven't already got this, bookmark it: http://perldoc.perl.org/ :)


All times are GMT -5. The time now is 11:57 AM.