Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need help with regex 2

Status
Not open for further replies.

netman4u

Technical User
Mar 16, 2005
176
US
Hello all,

I have a script I am working on that looks to me like it should be working but it does not. It takes 4 variables from the command line, opens up a config file and compares the command line args against the config file:

Code:
use strict;
use warnings;
my $prefix		= shift @ARGV;
my $cpu			= shift @ARGV;
my $sched_name	= shift @ARGV;
my $job_name	= shift @ARGV;
chomp ($prefix,$cpu,$sched_name,$job_name);
print "$prefix $cpu $sched_name $job_name\n";

open (CFG, "/home/mt71124/scripts/maestro_inst.txt") or die ("Error opening config file: $1");
local $/ = '&';
while (<CFG>) {
	next if /^\#/;
	next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+(\w+)/;
	print "$1\n";
	exit;
}
close CFG;
print "Contact the application oncall for this prefix to remediate./n The workstation is $cpu the schedule is $sched_name the job is $job_name\n";

Here is the config file:

Code:
# EXAMPLE:
#
EW PRDAI080 EWSRUD These are UDB backups that will hold up the remainder of the RS batch cycle.  
Please kill any executing jobs and cancel all Jobs in the Job Stream in reverse order due to dependencies. 
Send an email to  RS Systems MPelletier stating that this action was taken.&
 
EW PRDAI085 EWSRDBUD EWDBABKUP These are UDB backups that will hold up the remainder of the RS batch cycle.  
Please kill any executing jobs and cancel all Jobs in the Job Stream in reverse order due to dependencies. 
Send an email to  RS Systems MPelletier stating that this action was taken.&

When I input EW PRDAI085 EWSRDBUD EWDBABKUP from the command line my regex is supposed to find the entry and grab all the text after the EW PRDAI085 EWSRDBUD EWDBABKUP up to the ampersand (&) but here is what I am getting:

Code:
# ./maestro_inst.pl EW PRDAI085 EWSRDBUD EWDBABKUP
EW PRDAI085 EWSRDBUD EWDBABKUP
These

If I change my regex to start at the beginning of the line I get nothing.

next unless /^$prefix\s+$cpu\s+$sched_name\s+$job_name\s+(\w+)/;

Any help is appriciated.



If at first you don't succeed, don't try skydiving.
 
netman4u,

Are there new line characters as shown or there are only two records seperated by new line characters.

If yes try with the following

Code:
next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+(.+)$/;

--------------------------------------------------------------------------
I never set a goal because u never know whats going to happen tommorow.
 
Thanks for the reply spookie but after changing the line to your code it prints nothing, not even the "These"

If at first you don't succeed, don't try skydiving.
 
Couple of points:

1) The reason it won't work when you anchor your regexp to the start of the string is because the text you're trying to match isn't at the start of
the string you get. Because your input record separator is '&', your second record for example begins with two newlines.

2) This will also mean your first record gets skipped, as it starts with a comment. You'll have to add a & character after your comment so as to
separate it from a record you do want to process.

3) Your capturing group only contains word characters (\w). This doesn't include spaces, which is why it stops matching after "These".

 
Thanks ishnid. Your reply got me a little farther. After mucking with the code for a while I have it to the point where it reads the first line at least. Here is the new code:

Code:
use strict;
use warnings;
my $prefix		= shift @ARGV;
my $cpu			= shift @ARGV;
my $sched_name	= shift @ARGV;
my $job_name	= shift @ARGV;
chomp ($prefix,$cpu,$sched_name,$job_name);

open (CFG, "/home/mt71124/scripts/maestro_inst.txt") or die ("Error opening config file: $1");
local $/ = '&';
while (<CFG>) {
	next if /^\#/;
	next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+(.*)/;
	print "$1\n";
	exit;
}
close CFG;

And here is the new config file:

Code:
&EW PRDAI080 EWSRUD This is sameple text #1 UDB backups that will hold up the remainder of the RS batch cycle.  
Please kill any executing jobs and cancel all Jobs in the Job Stream in reverse order due to dependencies. 
Send an email to  RS Systems MPelletier stating that this action was taken.&
 
&EW PRDAI085 EWSRDBUD EWDBABKUP This is sample text #2 UDB backups that will hold up the remainder of the RS batch cycle.  
Please kill any executing jobs and cancel all Jobs in the Job Stream in reverse order due to dependencies. 
Send an email to RS Systems MPelletier stating that this action was taken.&
 
&DEFAULT Contact the application oncall for this prefix to remediate. The workstation is $cpu the schedule is $sched_name the job is $job_name&

and here is the new output:

Code:
# ./maestro_inst.pl EW PRDAI085 EWSRDBUD EWDBABKUP
This is sample text #2 UDB backups that will hold up the remainder of the RS batch cycle.

It is only picking up the first line. It looks like the regex is only grabing to the first newline it sees.



If at first you don't succeed, don't try skydiving.
 
The dot character doesn't match newlines by default. You have to add the 's' modifier to the end of your regexp, i.e.:
Code:
next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+(.*)/s;
That'll also match the & at the end though. You could do a 'chomp' on the record first to get rid of that, or else specifically match non-ampersand chars, i.e.:
Code:
/$prefix\s+$cpu\s+$sched_name\s+$job_name\s+([^&]*)/;
 
Thanks ishnid that did it. Final code below:

Code:
use strict;
use warnings;
my $prefix		= shift @ARGV;
my $cpu			= shift @ARGV;
my $sched_name	= shift @ARGV;
my $job_name	= shift @ARGV;
chomp ($prefix,$cpu,$sched_name,$job_name);
open (CFG, "/home/mt71124/scripts/maestro_inst.txt") or die ("Error opening config file: $1");
local $/ = '&';
while (<CFG>) {
	next if /^\#/;
	next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+([^&]*)/;
	print "$1\n";
	exit;
}
close CFG;

Much trouble for a simple little script. I am definately rusty!

If at first you don't succeed, don't try skydiving.
 
Yes, I see some more "rust":

Code:
"Error opening config file: [red]$1[/red]");

[wink]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Your right Kevin. Interesting I haven't done any perl in a year or so and I look at some of the scripts I wrote when I was doing some serious programming and I wonder how the hell I wrote those complicated 1000 line scripts and I relaize I didn't write them, you experts did one sub routine at a time.

Cheers to all you folks! I wish I could give more stars to you especially you Kevin who always seems to give me code I can unserstand when I know you could do it much more eligantly in code I would not!

[thumbsup]

If at first you don't succeed, don't try skydiving.
 
Want to add more elegance? Note, this won't affect how your script behaves one bit, so if you're not interested, feel free to stop reading here.

By default, "shift" operates on @ARGV, unless it's in a subroutine, in which case it operates on @_ (that's a slight simplification). In other words, you don't have to bother typing @ARGV at all! This'll do exactly the same thing:
Code:
my $prefix        = shift;
my $cpu            = shift;
my $sched_name    = shift;
my $job_name    = shift;

But if you preferred, you can just do that all on one line instead:
Code:
my ( $prefix, $cpu, $sched_name, $job_name ) = @ARGV;

The latter is how I'd do it.

Also, I'm pleased to notice that you've used the "local" modifier when changing your input record separator. Just something to be aware of: when you've changed it like that using "local", that change is limited to the block of code the declaration is in. Since in your example it isn't actually contained in a block, it'll still change the separator for your entire script. Happily, you can limit its effect to just that one file by enclosing the whole thing in a block of its own, like so:
Code:
{ # ... start the block
   local $/ = '&';
   while (<CFG>) {
      next if /^\#/;
      next unless /$prefix\s+$cpu\s+$sched_name\s+$job_name\s+([^&]*)/;
      print "$1\n";
      exit;
   }
} # ... end the block
# $/ gets its original value back here
close CFG;

I know for this script it's exiting once it finds the line you're looking for, but it's something to keep in mind in future.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top