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

trying to build a regular expression to match bus names in a design.

so if the bus is pce_rx_n[15:0], I want to be able to match pce_rx_n1 but not pce_rx_n10...pce_rx_n15

I can't figure out what to put at the end of the regex..

I can't use a dollar at the end of the regex because i also want to match pce_rx_n1_blah

I've tried /pce_rx_n1\D/ but that only works for the pce_rx_n1_blah case

/pce_rx_n1\D?/ doesn't work because no \D will match

I thought this might be the answer... but no dice /pce_rx_n1[\D$]?/

#!/usr/bin/perl -w use strict; #setup bus pins my @pinList=(); for my $i (0..15) { push @pinList,"pce_rx_n$i"; push @pinList,"pce_rx_p$i"; push @pinList,"pce_tx_n$i"; push @pinList,"pce_tx_p$i"; push @pinList,"cwx_tx_n${i}_blah"; push @pinList,"cwx_rx_p${i}bleh"; } # #Here lies the match string I am trying to build #I loosened it up more to match the tx or rx pins with any # pce or cwx prefix #my $match_str="[tr]x_n1[\\D\$]"; # #here is the Fix from Anaomalous Monk using the zero width #negative look-ahead assertion # my $match_str="[tr]x_n1(?!\\d)"; print "match_str=$match_str\n"; #now highlight any matches foreach my $pn (@pinList){ print "$pn"; if ($pn=~/$match_str/i) { print "***"; } print"\n"; }

Replies are listed 'Best First'.
Re: regular expression to match specific members of a bus_name
by AnomalousMonk (Archbishop) on Feb 12, 2016 at 04:50 UTC

    I still don't really understand the number range you're trying to isolate (use  <code> tags on anything with  [ ] in it, or else  &#91; &#93; HTML entities), but here's something to maybe get started with:


    Give a man a fish:  <%-{-{-{-<

      Thanks! Despite the murkiness of my question, you provided the magic I was looking for:

       my $match_str="[tr]x_n1(?!\\d)";

      It was the zero-width negative look-ahead assertion  (?!\d) that I was looking for

      BTW your use of map is spinning my head :) I will also be looking into qr

        qr// is definitely worth knowing about and using in regex composition. And map/grep are quite useful too.


        Give a man a fish:  <%-{-{-{-<

Re: regular expression to match specific members of a bus_name
by Laurent_R (Canon) on Feb 12, 2016 at 07:30 UTC
    Please use <code> tags for your string patterns, it is currently very difficult to figure out exactly what you need.

    A shoot in the dark which, even if it may not be exactly what you need, might still provide you some help::

    my $regex = qr/\w{3}_[tr]x_[pn]\d/;

      Sorry, I am trying to match a word segment with a specific number in it, but there can't be any extra digits following that number. I think I might have cleared that up when I updated the question

      if I am looking for foo1 then:

      foo1 should match but foo10 should not match

      and foo1bar should match but foo10bar should not match

      if I were looking for bar25 then:

      bar2 would not match, bar25 would match , bar250 would not match

      bar25foo would match and bar250foo would not match

      Thanks for the help! I think the AnamolousMonk has my solution

        Yes, it seems that you've figured it out by now, thanks to AnamolousMonk: the easiest way for achieving what you want is a negative look-ahead assertion:
        my $regex = qr/\w{3}_[tr]x_[pn]\d(?!\d)/;
        But even if you did not know about zero-width assertions, you could still have obtained more or less the same resukt with an alternation:
        my $regex = qr/\w{3}_[tr]x_[pn]\d(\D|$)/;
        which means: match everything to the required digit, followed by either a non-digit or the end of the string.

        TIMTOWTDI.

Re: regular expression to match specific members of a bus_name
by hippo (Archbishop) on Feb 12, 2016 at 09:40 UTC

    Hello, boleary. Welcome to the Monastery. Like others who have already responded it isn't entirely clear to me what precisely you are trying to achieve. Since you weren't here last week you likely won't have seen an excellent post on How to ask better questions using Test::More and sample data. Please consider taking a moment to read through this and see if you can't provide a piece of sample code in the manner suggested in that article which will likely help both you and us. If you have any comments to make on the meditation itself I'm sure those would also be welcome.

    Thanks.

      Thanks hippo.. I was not aware of the Test::More library, I do think that it works to explain what I was looking to do pretty well

      I included the tests with the working and non working regex

      #!/usr/bin/perl use strict; use warnings; use Test::More; my $regex = "/pce_rx_n1/"; like( "pce_rx_n1", $regex, "Matching my regex" ); like( "pce_rx_n1_blah", $regex, "Matching my regex" ); # #these fail because my $regex matches n1 and n10 and n13 # unlike( "pce_rx_n13", $regex, "Not Matching my regex" ); unlike( "pce_rx_n10_blah", $regex, "Not Matching my regex" ); #fix the regex with the #zero look-ahead negative assertion $regex = "/pce_rx_n1(?!\\d)/"; like( "pce_rx_n1", $regex, "Matching my regex" ); like( "pce_rx_n1_blah", $regex, "Matching my regex" ); unlike( "pce_rx_n12", $regex, "Not Matching my regex" ); unlike( "pce_rx_n10_blah", $regex, "Not Matching my regex" ); done_testing;

        Thank you - that is much clearer. Here is your code with only the first regex changed and it now passes all the tests. HTH, Hippo.

        #!/usr/bin/perl use strict; use warnings; use Test::More; my $regex = qr/pce_rx_n1\D*$/; like( "pce_rx_n1", $regex, "Matching my regex" ); like( "pce_rx_n1_blah", $regex, "Matching my regex" ); # #these fail because my $regex matches n1 and n10 and n13 # unlike( "pce_rx_n13", $regex, "Not Matching my regex" ); unlike( "pce_rx_n10_blah", $regex, "Not Matching my regex" ); #fix the regex with the #zero look-ahead negative assertion $regex = "/pce_rx_n1(?!\\d)/"; like( "pce_rx_n1", $regex, "Matching my regex" ); like( "pce_rx_n1_blah", $regex, "Matching my regex" ); unlike( "pce_rx_n12", $regex, "Not Matching my regex" ); unlike( "pce_rx_n10_blah", $regex, "Not Matching my regex" ); done_testing;
Re: regular expression to match specific members of a bus_name
by Anonymous Monk on Feb 12, 2016 at 04:51 UTC
    Are you sure about what \D means?

      I thought it meant not a digit?

        What AnonyMonk may be getting at is the sometimes tricky difference between \D and (?! \d):

        • \D requires the presence of a non-digit character, so 'xyz1' will not match against /\d\D/;
        • (?! \d) only requires the absence of a digit character, and the end of the string qualifies as this absence so 'xyz1' will match against /\d(?!\d)/ — as you have discovered!
        c:\@Work\Perl\monks>perl -wMstrict -le "my $s = 'xyz1'; ;; print '/\d \D/ matches' if $s =~ m{ \d \D }xms; print '/\d (?! \d)/ matches' if $s =~ m{ \d (?! \d) }xms; " /\d (?! \d)/ matches


        Give a man a fish:  <%-{-{-{-<