G'day pravakta,

Welcome to the Monastery.

"Can any body highlight the issue with my code?"

Firstly, there seems to be a mismatch between your stated intent (i.e. "print each number") and the example code that you're using to achieve this (that particular example is demonstrating the use of the '\G' assertion in regexes). I'll attempt to point out where I think you've taken ideas from the example and incorrectly (or, perhaps, just naïvely) used them in your code: that will, of course, just be guesswork.

In the examples below, I've used the alias perle. It saves a lot of typing and should make the one-liners easier for you to read. It's intended to catch many problems and also enable all the features of my current Perl version (5.26.0).

$ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -E'

You're using a named capture; I can't see any need for this here. While you're learning, I'd certainly encourage you to try lots of different things; however, start off simply; get that working; then add a new concept; get that working; and so on. When you try to do too much at once, you can end up with a "can't see the wood for the trees" situation. Just to show that level of complexity is unnecessary here:

$ perle 'my $x = "1 12 123"; while ($x =~ /(?<w>\d+)/g) { say $+{w} }' 1 12 123 $ perle 'my $x = "1 12 123"; while ($x =~ /(\d+)/g) { say $1 }' 1 12 123

I won't use the named capture in any further examples. You may want to extend my examples, using named captures, for your own learning experience. I did notice that the main difference between your code and the example, in this area, was "?<weight>" vs. "[+-]?": if that's presenting you with some confusion, or other difficulty, that you can't resolve, just ask.

As AnomalousMonk thought, your anchors are causing problems. Compare these with the last example:

$ perle 'my $x = "1 12 123"; while ($x =~ /^(\d+)/g) { say $1 }' 1 $ perle 'my $x = "1 12 123"; while ($x =~ /(\d+)$/g) { say $1 }' 123 $ perle 'my $x = "1 12 123"; while ($x =~ /^(\d+)$/g) { say $1 }' $

The '^' anchor (start of string) is the only one used in the example code: it has no '$' anchor (end of string). I suspect the 'g' modifier may be at the root of some confusion. Your code wants it for mutliple matches, i.e. each of the numbers in the string. The example code wants it for a completely different reason: as its regex is anchored to the start of the string, it will only match once; it needs that modifier for the correct operation of the '\G' assertion later in the code.

I see you commented out this assignment: "#my $weight = $1;". It's important to understand that capture variables ('$1', '%+', etc.) are cleared whenever a new regex is encountered. Unless you're using those values immediately after the regex, you should assign them to another variable for subsequent use. Compare these:

$ perle 'my $x = "123"; $x =~ /(1)/; say $1' 1 $ perle 'my $x = "123"; $x =~ /(1)/; say $1 if $x =~ /2/' Use of uninitialized value $1 in say at -e line 1. $ perle 'my $x = "123"; $x =~ /(1)/; my $y = $1; say $y' 1 $ perle 'my $x = "123"; $x =~ /(1)/; my $y = $1; say $y if $x =~ /2/' 1

In general, it's good practice to do that anyway: it's called defensive programming. Although your original code might use '$1' immediately after the regex, a later code change might introduce one or more intervening lines: with code more complex than the simple examples here, the effect of adding new code may not be immediately obvious, and, whenever it does becomes noticeable, the source of the bug may not be easy to find.

The "\s*" in the example code is to eat up any optional whitespace before the units ("kg." or "lbs."); the next regex can start to match those units immediately. It is not needed in your code because you're only capturing strings of digits; in fact, it doesn't matter whether the numbers are separated by spaces or something else:

$ perle 'my $x = "1 12 123"; while ($x =~ /(\d+)\s*/g) { say $1 }' 1 12 123 $ perle 'my $x = "1_12_123"; while ($x =~ /(\d+)\s*/g) { say $1 }' 1 12 123 $ perle 'my $x = "1_12_123"; while ($x =~ /(\d+)/g) { say $1 }' 1 12 123

Your final line of code

print "Weight:\n" unless $x=~/Gkg\./g;

has a number of issues.

You have a prompt for "Weight:" but no value. You should reinstate the assignment to '$weight' and include it in the output. You can't use '$1' (or '$+{weight}') because the unless condition will be evaluated first and, as shown above, that contains a regex and existing capture values will be wiped.

You've attempted to copy the "/\Gkg\./g" from the example (I suspect without really understanding that piece of code).

I don't think you really want to conditionally print anyway; however, if you do, you'll need something completely different.

This isn't related to your code; however, I thought I'd just point out this potential gotcha. When a '\G' assertion is used in a loop condition, without a 'g' modifier, this type of infinite loop may result (which I've trapped here after a thousand iterations):

$ perle ' my $x = "AB"; my $c = 0; $x =~ /A/g; while ($x =~ /\GB/) { ++$c; last if $c > 1000; } say $c; ' 1001

Avoid that by using a 'g' modifier:

$ perle ' my $x = "AB"; my $c = 0; $x =~ /A/g; while ($x =~ /\GB/g) { ++$c; last if $c > 1000; } say $c; ' 1

— Ken


In reply to Re: Regular expression by kcott
in thread Regular expression by pravakta

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.