Re: RegEx Multi-Line Matching
Jeff Westman wrote: On 6/20/05, John W. Krahn [EMAIL PROTECTED] wrote: It looks like you don't really need to use paragraph mode, this should do what you want: #!/usr/bin/perl # # tnsnames.pl -- reads tnsnames.ora, sorts by host name use warnings; use strict; my $tnsFile = 'tnsnames.ora'; open F, '', $tnsFile or die Could not open file $tnsFile: $!\n; my ( $host, $name, %tns ) = ( '', '' ); while ( F ) { $host = $1 if /\(HOST\s*=\s*(\w+)\)/; $name = $1 if /\(SERVICE_NAME\s*=\s*(\w+)\)/; if ( length $host and length $name ) { print *** RESULT : host= $host, service= $name\n; $tns{ $host } = $name; ( $host, $name ) = ( '', '' ); } } close F; for ( sort keys %tns ) { printf %-8s = %s\n, $_, $tns{ $_ }; } __END__ Thank you for your post. I know I could have just done some top-down scanning for pairs (I like your style, BTW), but it seemed safer to do multi-line matching, so I am still a bit bothered why I couldn't get the match to work in all cases (ie, a blank line was mandatory). I also had a basic question on the code you sent. You have: $host = $1 if /\(HOST\s*=\s*(\w+)\)/; $name = $1 if /\(SERVICE_NAME\s*=\s*(\w+)\)/; This works and makes sense. But what if the line is commented?! That is, when I modified this and made this: $host = $1 if /[^#].*\(HOST\s*=\s*(\w+)\)/; $name = $1 if /[^#].*\(SERVICE_NAME\s*=\s*(\w+)\)/; it SHOULD have worked (I think!). It still matched a line that should have been ignored. What am I doing wrong?! The problem is that [^#] can match anywhere so in the string ab#cd(HOST = xyz) it can match at 'a' or 'b' or 'c' or 'd'. This should work better: my $para = ''; while ( F ) { $para .= $_; next if $para =~ tr/(// != $para =~ tr/)//; $para =~ s/#.*//g; # remove comment lines if ( $para =~ /\(HOST\s*=\s*(\w+)\).*?\(SERVICE_NAME\s*=\s*(\w+)\)/s ) { print *** RESULT : host= $1, service= $2\n; $tns{ $1 } = $2; } $para = ''; } for ( sort keys %tns ) { printf %-8s = %s\n, $_, $tns{ $_ }; } John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
Re: Regex Multi-Line Matching
Hey Chris, I'm not spamming anyone. I had an error when I sent my email(s) so I resent it. Sorry you had to click the mouse an additional time to 'delete'. Jeff On 6/20/05, Chris Devers [EMAIL PROTECTED] wrote: On Mon, 20 Jun 2005, Jeff Westman wrote: Any help would be greatly appreciated. We heard you the first two times. Please stop spamming the list with the same question. -- Chris Devers -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
RegEx Multi-Line Matching
Hello Fellow Perlites, I'm having difficulty parsing a file and could use some help here. I've attached my code, output file, and sample job run. Basically, I want to read an Oracle TNS file (tnsnames.ora) and list the host name and service on that server based on this input file. A sample TNS entry is multi-lined and looke like this mysprdtmp = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = mxr)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = mysprd01) ) ) So, when the script runs, I would get this at end of job: mx01 = tmsprd01 mx16 = mystst04 mxp = mysdev07 mxq = mystst02 mxr = mysprd01 s0869u03 = rdmtst06 ux08 = rdmtst03 uxb = scsdev01 The script generally works fine, but it has a problem when I do not have a blank line in between these entries. In other words, if my input file has mysbse = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = mysbse) ) ) oemdev = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = oemdev) ) ) it should recognize the new TNS listing and give me mxp = mysbse mxp = oemdev (along with the others I am parsing). Again, if I separate the two with a blank line, it works fine. But since this is a DBA-owned file, I cannot do this. My regex looks like my $tnsEntry = 'EOF'; ^ \s*\w+\s*=\s* \s+\(DESCRIPTION\s*= \s+\(ADDRESS_LIST\s*=\s* \s+\(ADDRESS\s*=\s*\(PROTOCOL\s*=\s*TCP\)\(HOST\s*=\s*(\w+)\)\(PORT\s*=\s*\d+\)\) \s+\)\s* \s+\(CONNECT_DATA\s*=\s* \s+\(SERVER\s*=\s*\w+\) \s+\(SERVICE_NAME\s*=\s*(\w+)\) # \s+\)\s* # \s+\) $ EOF Any help would be appreciated. I've been at this off and on for several days. Note, this is not a production file, but just a utility script. Thanks Jeff -- perl script follows (tnsnames.pl): -- #!/usr/bin/perl # # tnsnames.pl -- reads tnsnames.ora, sorts by host name use warnings; use strict; my $host; my $name; my %tns; my @sortKeys; my $key; my $val; my $para; my $matchNbr; $/ = ''; # problem: tns entries with no line break are not distiquished my $tnsEntry = 'EOF'; ^ \s*\w+\s*=\s* \s+\(DESCRIPTION\s*= \s+\(ADDRESS_LIST\s*=\s* \s+\(ADDRESS\s*=\s*\(PROTOCOL\s*=\s*TCP\)\(HOST\s*=\s*(\w+)\)\(PORT\s*=\s*\d+\)\) \s+\)\s* \s+\(CONNECT_DATA\s*=\s* \s+\(SERVER\s*=\s*\w+\) \s+\(SERVICE_NAME\s*=\s*(\w+)\) # \s+\)\s* # \s+\) $ EOF die ORACLE_HOME is not defined!\n unless (defined($ENV{ORACLE_HOME} )); my $tnsFile = ./tnsnames.ora; open(F, $tnsFile) or die Could not open file $tnsFile: $!\n; while (chomp($para = F)) { undef($host); undef($name); if ($para =~ m[$tnsEntry]msxo) { $matchNbr++; print -x80, \n; print *** match #$matchNbr : $para\n; $host = $1; $name = $2; print *** RESULT : host= $host, service= $name\n; if ((defined($host)) (defined($name))) { $tns{$host} = $name; } } last if eof(F); } close(F); @sortKeys = sort keys(%tns); foreach (@sortKeys) { printf %-8s = $tns{$_}\n, $_; } -- sample input file follows (tnsnames.ora) -- # TNSNAMES.ORA Network Configuration File: /u01/app/oracle/product/9.2.0/network/admin/tnsnames.ora # Generated by Oracle configuration tools. # # history: # 05/27/04,kk Added rdmdev02 and scsdev01 # 06/01/04,js Added rdmtst02 and rdmtst03 per j.jonawski # 08/08/04,gv Added mysdev08 # 09/15/04,gv Added mystst04 # 09/20/04,cd Added mysdev04 ## mxp ### ## Reports server repserver_mysbse=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1960)) repserver_mysdev01=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1981)) repserver_mysdev02=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1982)) repserver_mysdev03=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1983)) repserver_mysdev04=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1984)) repserver_mysdev05=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1985)) repserver_mysdev06=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1986)) repserver_mysdev07=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1987)) repserver_mysdev08=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1988)) repserver_mysdev04=(ADDRESS = (PROTOCOL = TCP)(HOST = mxp)(PORT = 1989)) ## mxr ### mysprdtmp = (DESCRIPTION =
Regex Multi-Line Matching
My problem is simple. I want to parse an Oracle TNS file, listing host and the service it provides. A sample TNS entry is multi-lined and looks like this: mysprdtmp = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = mxr)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = mysprd01) ) ) The regex I am using to parse this looks like so: mysprdtmp = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = mxr)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = mysprd01) ) ) My code snippit is like this: while (chomp($para = F)) { undef($host); undef($name); if ($para =~ m[$tnsEntry]msxo) { } The problem is, that this works great, EXCEPT for cases where I do not have a blank line separating two concatenated TNS entries (I only get the last one). Any help would be greatly appreciated. Thanks Jeff -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
Re: Regex Multi-Line Matching
On Mon, 20 Jun 2005, Jeff Westman wrote: Any help would be greatly appreciated. We heard you the first two times. Please stop spamming the list with the same question. -- Chris Devers -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
Re: RegEx Multi-Line Matching
Jeff Westman wrote: Hello Fellow Perlites, Hello, I'm having difficulty parsing a file and could use some help here. I've attached my code, output file, and sample job run. Basically, I want to read an Oracle TNS file (tnsnames.ora) and list the host name and service on that server based on this input file. A sample TNS entry is multi-lined and looke like this [snip] The script generally works fine, but it has a problem when I do not have a blank line in between these entries. In other words, if my input file has [snip] (along with the others I am parsing). Again, if I separate the two with a blank line, it works fine. But since this is a DBA-owned file, I cannot do this. [snip] Any help would be appreciated. I've been at this off and on for several days. Note, this is not a production file, but just a utility script. Thank you for providing a working program and data to test it with. It looks like you don't really need to use paragraph mode, this should do what you want: #!/usr/bin/perl # # tnsnames.pl -- reads tnsnames.ora, sorts by host name use warnings; use strict; my $tnsFile = 'tnsnames.ora'; open F, '', $tnsFile or die Could not open file $tnsFile: $!\n; my ( $host, $name, %tns ) = ( '', '' ); while ( F ) { $host = $1 if /\(HOST\s*=\s*(\w+)\)/; $name = $1 if /\(SERVICE_NAME\s*=\s*(\w+)\)/; if ( length $host and length $name ) { print *** RESULT : host= $host, service= $name\n; $tns{ $host } = $name; ( $host, $name ) = ( '', '' ); } } close F; for ( sort keys %tns ) { printf %-8s = %s\n, $_, $tns{ $_ }; } __END__ John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response