CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Advanced:
Help with parse words please.

 



cuboidgraphix
User

Feb 20, 2009, 3:07 PM

Post #1 of 11 (4718 views)
Help with parse words please. Can't Post

Hi guys,
I'm back. Tongue I've got a lil problem with my parser. This is the basic example...


Code
#!/usr/bin/perl 
# This file is the parser.pl
# This is a script that will parse data from the Syslog

use strict;
use warnings;
use Text::ParseWords;

my $FILE = $ARGV[0] || die "Usage: $0 <filename>\n";
open my $FH, '<', $FILE or die "Can't open '$FILE' $!";

while (<$FH>) {
my @words = &quotewords('[\s;\%]+', 0, $_);
my $i = 0;
foreach (@words) {
print "$i: <$_>\n";
$i++;
}
}

close $FH;


OK my delimiters are [\s;\%] so far.

I was wondering.. is there a way to make two letters (for example 'ms') a delimiter?

I have tried.. [\s;\%\ms] but this only makes 'm' a delimiter..

is there a way to make the two letters a delimiter?

Please and thanks for any help given.


KevinR
Veteran


Feb 20, 2009, 3:51 PM

Post #2 of 11 (4714 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

maybe:


Code
my @words = &quotewords('[\s;\%]+|ms', 0, $_);


The characters inside the square brackets are called a character class. The order of the characters is ignored, so you can't have 'ms' inside a character class and hope both characters are used as one.
-------------------------------------------------


cuboidgraphix
User

Feb 21, 2009, 8:34 AM

Post #3 of 11 (4703 views)
Re: [KevinR] Help with parse words please. [In reply to] Can't Post

Hi Kevin,
Thanks for the tip. It did work to a certain extent.. this is my output.


Code
0: <.SPEEDNET> 
1: <ACT102>
2: <FEB20>
3: <13:59:02>
4: <5800>
5: <INFO>
6: <ACTIVITY_SUMMARY>
7: <Summary:>
8: <Catmp/hr>
9: <24624>
10: <Lorig>
11: <0>
12: <Torig>
13: <410>
14: <ToAnn>
15: <19>
16: <Cpocc>
17: <20>
18: <Conctr>
19: <115>
20: <OAvgDel>
21: <15>
22: <>
23: <O95>
24: <lim>
25: <40>
26: <>
27: <PAvgDel>
28: <13>
29: <>
30: <P95>
31: <lim>
32: <26>
33: <>
34: <BAvgDel>
35: <13>
36: <>
37: <B95>
38: <lim>
39: <27>
40: <>
41: <RTrip>
42: <0>
43: <>
44: <Origdeny>
45: <0>
46: <Inefdeny>
47: <0>
48: <CPloovfl>
49: <0>
50: <CPsuic>
51: <0>
52: <CPtrap>
53: <0>
54: <LCMdtsr>
55: <0>
56: <LMdtsr>
57: <0>
Use of uninitialized value in concatenation (.) or string at ./test.pl line 16, <$FH> line 1.
58: <>


Is there a way to remove lines 22, 26 ... etc.?

The thing is that in line 21, 25 ... etc.. we had the value example for 21... we had the value ... '15ms' but after removing the ms I got an additional like.. 22 <>

Thanks again.


FishMonger
Veteran / Moderator

Feb 21, 2009, 8:40 AM

Post #4 of 11 (4702 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

print "$i: <$_>\n" if $_;

or

print "$i: <$_>\n" if defined $_;

or

print "$i: <$_>\n" if length $_;


cuboidgraphix
User

Feb 21, 2009, 9:02 AM

Post #5 of 11 (4700 views)
Re: [FishMonger] Help with parse words please. [In reply to] Can't Post


In Reply To
print "$i: <$_>\n" if $_;

or

print "$i: <$_>\n" if defined $_;

or

print "$i: <$_>\n" if length $_;



Thanks Fish.. but this isn't exactly what I had in mind. The thing is... this is just a sample script I'm basing another longer script on. The reason why I'm using this is because like this I can find the line position so I can use this piece of code which you guys had helped me on before on a similar parse.


Code
# Parsing the Line 
my ($TIME,$Catmp,$Lorig,$Torig,$ToAnn,$Cpocc,$Conctr,$OAvgDel,$O95,$PAvgDel,$P95,$BAvgDel,$B95,$RTrip,$Origdeny,$Inefdeny,$CPloovfl,$CPsuic,$CPtrap,$LCMdts
r,$LMdtsr) = (quotewords('[\s;\%]+', 0, $data))[3,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47];


And honestly ... I want the script to be able to pin point the position right, and having an empty line... <> does give me doubts. I wanted to know if there's any way (an additional delimiter) which would deal with the <> problem. The delimters.. [\s;\%]+ work fine... the problem is trying to get rid of the 'ms' in the following.


Code
0: <.SPEEDNET> 
1: <ACT102>
2: <FEB20>
3: <13:59:02>
4: <5800>
5: <INFO>
6: <ACTIVITY_SUMMARY>
7: <Summary:>
8: <Catmp/hr>
9: <24624>
10: <Lorig>
11: <0>
12: <Torig>
13: <410>
14: <ToAnn>
15: <19>
16: <Cpocc>
17: <20>
18: <Conctr>
19: <115>
20: <OAvgDel>
21: <15ms>
22: <O95>
23: <lim>
24: <40ms>
25: <PAvgDel>
26: <13ms>
27: <P95>
28: <lim>
29: <26ms>
30: <BAvgDel>
31: <13ms>
32: <B95>
33: <lim>
34: <27ms>
35: <RTrip>
36: <0ms>
37: <Origdeny>
38: <0>
39: <Inefdeny>
40: <0>
41: <CPloovfl>
42: <0>
43: <CPsuic>
44: <0>
45: <CPtrap>
46: <0>
47: <LCMdtsr>
48: <0>
49: <LMdtsr>
50: <0>
Use of uninitialized value in concatenation (.) or string at ./test.pl line 16, <$FH> line 1.
51: <>


I could probably get rid of it using substring... but that just means more code for each line that contains ms... I wanted to do it in one swift way... for ecample.. '[\s;\%]+|ms'. This works, only that it then gives an additional empty line <> right after.


KevinR
Veteran


Feb 21, 2009, 10:01 AM

Post #6 of 11 (4694 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

'ms' is not a delimiter so using split() is not the right approach to get rid of the unwanted characters. You should use a regexp or substr or possibly the tr/// operator to remove unwanted characters from a string.
-------------------------------------------------


cuboidgraphix
User

Feb 21, 2009, 10:03 AM

Post #7 of 11 (4694 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

OK guys... I got it done using another method...

I used the substitution thingie..

# Stripping the data output of '\n' new lines, 'ms' and '%' signs
$data =~ s/(\n)|(ms)|(%)//g;


Then... when parsing the data I only used one delimiter..

(quotewords('[\s]+', 0, $data)) which was the space.

Worked perfect. Smile

Well i just wanna say thanks guys for putting time and effort into helping me.

Thanks!!!!


KevinR
Veteran


Feb 21, 2009, 10:40 AM

Post #8 of 11 (4690 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

You're welcome Cool
-------------------------------------------------


cuboidgraphix
User

Feb 22, 2009, 6:43 AM

Post #9 of 11 (4675 views)
Re: [KevinR] Help with parse words please. [In reply to] Can't Post

Here's my final code.


Code
#!/usr/bin/perl 
# This is a script that will telnet into the MTX and gather the BRSTAT OM(s).

# Declare 'use' statements
use DBI;
use strict;
use warnings;
use DBD::mysql;
use Net::Telnet;
use Text::ParseWords;
use POSIX qw/strftime/;

# Establish the MySQL connection
my($host,$database,$usr,$pwd,$dsn,$dbh,$sth,$query);
$host = 'localhost';
$database = 'db';
$usr = 'USR';
$pwd = 'PWD';

# Data Source Name
$dsn = "dbi:mysql:$database:localhost:3306";

# Perl DBI connect
$dbh = DBI->connect($dsn, $usr, $pwd);

# Establish the Telnet Connection
my($user,$pass,$server,$t,$data);
$user="USER";
$pass="PASS";
$server="HOST";
$t = Net::Telnet->new($server);
$t->waitfor('/Enter User Name/');
$t->print("$user");
$t->waitfor('/Enter Password/');
$t->print("$pass");
$t->waitfor('/>/');
$t->print("logutil;open act 102");
$t->waitfor('/Done./');

# Collecting data output
($data) = $t->waitfor('/>/');

$t->print("logout");

# Stripping the data output of lines, ms and %.
$data =~ s/(\n)|(ms)|(%)//g;

# Short script to print the output in a text file for test.pl
# my($FH,$FILE);
# $FILE = "sample.txt";
# open $FH, '>', $FILE or die "Can't open '$FILE' $!";
# print $FH $data;
# close $FH;

if($data =~ /^SPEEDNET/){

# Parsing the Line
my ($TIME,$Catmp,$Lorig,$Torig,$ToAnn,$Cpocc,$Conctr,$OAvgDel,$O95,$PAvgDel,$P95,$BAvgDel,$B95,$RTrip, $Origdeny,$Inefdeny,$CPloovfl,$CPsuic,$CPtrap,$LCMdtsr,$LMdtsr) = (quotewords('[\s]+', 0, $data))[3,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47];

# Date variable
my $DATE = strftime("%Y-%m-%d", localtime(time));
# Prepare and execute query to insert into the database
$query = "INSERT INTO ACT_102 VALUES('$DATE','$TIME','$Catmp','$Lorig','$Torig','$ToAnn','$Cpocc','$Conctr','$OAvgDel','$O95','$PAvgDel', '$P95','$BAvgDel','$B95','$RTrip','$Origdeny','$Inefdeny','$CPloovfl', '$CPsuic','$CPtrap','$LCMdtsr','$LMdtsr')";
$sth = $dbh->prepare($query);
$sth->execute();

$sth->finish();
$dbh->disconnect();
}


Don't know what rating my script has... but I tried to use best perl practices. :)


(This post was edited by cuboidgraphix on Feb 22, 2009, 6:46 AM)


FishMonger
Veteran / Moderator

Feb 22, 2009, 10:25 AM

Post #10 of 11 (4666 views)
Re: [cuboidgraphix] Help with parse words please. [In reply to] Can't Post

For the most part, that's pretty good. However, you could tweak it a little if you really want to follow the guidelines of Best Practices.

Vars should be declared not only in the smallest scope, but where they're needed without duplication.

e.g.,

Code
my($host,$database,$usr,$pwd,$dsn,$dbh,$sth,$query);  
$host = 'localhost';
$database = 'db';
$usr = 'USR';
$pwd = 'PWD';

Best Practice would be:

Code
my $host = 'localhost';  
my $database = 'db';
my $usr = 'USR';
my $pwd = 'PWD';
...
...
...


Your db connect statement should include a die statement.

As much as possible, the line lengths should be kept below 80 col/chars (72 or below is ideal). If a statement is above that "limit", then break it up into multiple lines and long lists, such as your var assignments when parsing the line, should be put into col/row format.

Which means this:

Code
my ($TIME,$Catmp,$Lorig,$Torig,$ToAnn,$Cpocc,$Conctr,$OAvgDel,$O95,$PAvgDel,$P95,$BAvgDel,$B95,$RTrip, $Origdeny,$Inefdeny,$CPloovfl,$CPsuic,$CPtrap,$LCMdtsr,$LMdtsr) = (quotewords('[\s]+', 0, $data))[3,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47];

would become:

Code
my ($TIME,     $Catmp,   $Lorig,  $Torig,   $ToAnn, $Cpocc, $Conctr,   $OAvgDel, 
$O95, $PAvgDel, $P95, $BAvgDel, $B95, $RTrip, $Origdeny, $Inefdeny,
$CPloovfl, $CPsuic, $CPtrap, $LCMdtsr, $LMdtsr
) = (quotewords('[\s]+', 0, $data))[3,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47];

but even that would need to be tweaked a little more.

Personally, I'd probably put that data into an array instead of the individual scalars and use place holders in the prepare statement.

The prepare and execute statements should include error checking.


cuboidgraphix
User

Feb 25, 2009, 7:01 PM

Post #11 of 11 (4647 views)
Re: [FishMonger] Help with parse words please. [In reply to] Can't Post

Thanks Fish,
I'll definitely follow your advice. You guys have helped me come a long way into understanding the Perl Language and I thank you for that.

Regards.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives