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

Greetings Monks. I am having issues with my regex that is driving me NUTS!! Here's the scenario:

I have the following data assigned to variable $BE_temp:

+--------------+-------------+ | version_name | schema_name | +--------------+-------------+ | dsmgt_03_03 | dsmgt_03 | +--------------+-------------+
I need to extract the two "dsmgt*" pieces into 2 different variables. I have tried a multitude of methods, but none are working. The latest attempt:
$BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/m; my $LSV = $1; my $LSN = $2;

Any thoughts on what I've got wrong? I'm the first to admit that RE is not my strong suit...

Thank you in advance for the assistance!!

Replies are listed 'Best First'.
Re: Issues With Regex
by choroba (Cardinal) on Jan 07, 2014 at 22:41 UTC
    Works for me. Did you print the results?
    #!/usr/bin/perl use warnings; use strict; my $BE_temp = '+--------------+-------------+ | version_name | schema_name | +--------------+-------------+ | dsmgt_03_03 | dsmgt_03 | +--------------+-------------+ '; $BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/m; my $LSV = $1; my $LSN = $2; print "[$LSV] [$LSN]\n";

    Note that you are filling the variables even if the regex does not match. It might be better to fix that, plus avoid the $1 and $2:

    if (my ($LSV, $LSN) = $BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/ +m) { print "[$LSV] [$LSN]\n"; }
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Issues With Regex
by AnomalousMonk (Archbishop) on Jan 08, 2014 at 00:38 UTC

    Another approach:

    >perl -wMstrict -le "my $s = 'dsmgt dsmgt_ dsmgt_9 dsmgt99 dsmgt__99 dsmgt_999 ' . 'dsmgt_12_34_56dsmgt_12_34 dsmgt_12'; print qq{'$s'}; ;; my $rx_dsmgt = qr{ (?<! [[:alpha:]]) dsmgt (?: _ \d\d)+ (?! \d) }xms; ;; my @pieces = $s =~ m{ $rx_dsmgt }xmsg; printf qq{'$_' } for @pieces; " 'dsmgt dsmgt_ dsmgt_9 dsmgt99 dsmgt__99 dsmgt_999 dsmgt_12_34_56dsmgt_ +12_34 dsmgt_12' 'dsmgt_12_34_56' 'dsmgt_12_34' 'dsmgt_12'
Re: Issues With Regex
by ImJustAFriend (Scribe) on Jan 08, 2014 at 17:20 UTC

    OK, figured it out. My $BE_temp was being set by capturing the output of a MySQL query. I changed the output format of the query with the "-E" flag. I was then able to RE the LSV and LSN appropriately. Code from my test script and output below...

    $output = $cli->cmd("/usr/mysql/bin/mysql -E -uuser -ppass -D targetdb + -e \"select * from table;\" | tail -2"); $temp = $output; print "\ntemp\n----------------\n$temp\n"; my ($LSV, $LSN) = $temp =~ m/^.*: (\w+).*: (\w+)/s; print "LSV: $LSV\nLSN: $LSN\n";

    Results

    temp ---------------- version_name: dsmgt_03_03 schema_name: dsmgt_03 LSV: dsmgt_03_03 LSN: dsmgt_03
      my ($LSV, $LSN) = $temp =~ m/^.*: (\w+).*: (\w+)/s;
      print "LSV: $LSV\nLSN: $LSN\n";

      This still has the problem (IMHO) that the success of the match is not tested before using the 'results' of the match. Please see my reply above.

Re: Issues With Regex
by ImJustAFriend (Scribe) on Jan 08, 2014 at 13:42 UTC

    I am getting "uninitialized value" errors every time with this script. I just changed the code to the following:

    my ($LSV, $LSN) = $BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/m; if ( $LSV =~ m/dsmgt_03_03/ ) { print "LSV Match\n"; } else { print "LSV Fail\n"; }

    When I run my script now, I get the following:

    Use of uninitialized value $LSV in pattern match (m//) at C:\Users\civ +ey\Documents\Perl\SDM401-LDAP_Config.pl line 405, <STDIN> line 2. LSV Fail

    I will move the relevant pieces of code to a test script and see if that helps... any other ideas?

    Thanks!!

      my ($LSV, $LSN) = $BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/m;
      if ( $LSV =~ m/dsmgt_03_03/ ) { ... }

      If the initial match against  $BE_temp fails, the subsequent match against  $LSV will produce a "Use of uninitialized value $LSV in pattern match ..." warning (not error) because  $LSV et al are undefined. The initial match should be tested in some way and subsequent matches (or uses of the extracted strings) made dependent on a successful initial match, e.g.:

      if (my ($LSV, $LSN) = $BE_temp =~ m/^\|\s(\w+_\d+)\s+\|\s+(\w+)\s+\|$/ +m) { do_something_with($LSV); do_something_with($LSN); }

      What results are you expecting?