开发者

perl Regular expression scalar variables with `#use warnings;` enabled

I am trying to complete a college assignment in Perl, and we've been told by our professor to use:

use strict;
use warnings;

With use strict; my code works perfectly. with use warnings;, however, my code spews all this stuff to SDOUT and I don't know why (or how to shut it up). My relevant code is:

while($diff =~ /^(\d+)((,){1}(\d+))?([adc])(\d+)((,){1}(\d+))?/mgi) {
    # This line is used for debugging the $diff regular expression scalars.
    # print "\n1: $1\t2: $2\t 3: $3\t4: $4\t5: $5\t6: $6\t7: $7\t8: $8\t9: $9\n";

    $difflinestotal += ($4 - $1) unless $4 == "";
    $difflinestotal += ($9 - $6) unless $9 == "";
    $difflinestotal += 1 if (($4 == "") && ($9 == ""));
}

With warnings, it spits this out in the middle of my output:

Argument "" isn't numeric in numeric eq (==) at ./partc.pl line 145.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 145.
Argument "" isn't numeric in numeric eq (==) at ./partc.pl line 146.
Argument "" isn't numeric in numeric eq (==) at ./partc.pl line 147.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 147.
Argument "" isn't numeric in numeric eq (==) at ./partc.pl line 147.
Use of uninitialized value $9 in numeric eq (==) at ./partc.pl line 146.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 145.
Use of uninitialized value $9 in numeric eq (==) at ./partc.pl line 146.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 147.
Use of uninitialized value $9 in numeric eq开发者_开发技巧 (==) at ./partc.pl line 147.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 145.
Use of uninitialized value $4 in numeric eq (==) at ./partc.pl line 147.

...and it's messing up my formatting (I am generating a table in the console). I tried 'declaring' the scalars, but then (of course) those were in error. How can I get my Perl script to shut up with these warnings (especially since the works anyway)?


That goes to STDERR, not STDOUT.

Capture variables aren't always set; if they aren't, they will be undefined. For example, your regex has ((,){1}(\d+))? (where the (\d+) is the 4th capture). The ? makes the whole group optional. If it is not used in matching the string, $3 and $4 will be left undefined.

Where you are testing unless $4 == "" you should be testing if defined $4.

A couple other notes: {1} does nothing; it says that the preceding part of the regular expression should match exactly once - which it would do without the {1} too. It can be easier to keep track of which capture variables you are using if you use non-capturing groups ((?: ... )) for the groupings you don't need captured.


It's only working, if it is, by accident. What that regex captures is

  • $1 ((\d+)) is the first number

  • $2 (((,){1}(\d+))) is your rather verbosely captured comma ($3) followed by another number ($4). This will be undefined if it doesn't match

  • $3 ((,){1}) is a comma. What did you intend with this? (,) captures a comma, and {1} repeats that once (which is a no-op). If $2 doesn't match then this will be undefined.

  • $4 ((\d+)) is the number immediately following the comma. If $2 doesn't match then this will be undefined.

  • $5 (([adc])) captures one of a, d, or c.

  • $6 ((\d+)) captures another number.

  • $7 through $9 repeat $2 through $4, including all of them being undefined if $7 fails to match.

What does the data you're trying to match against look like?

Aside from the above, it's often helpful to use non-capturing groups ((?:...)) when you don't actually need something, so that the capture variables are more consistent (there are also some minor performance and memory improvements). In this case, I'd guess that $2 and $7 above don't need to be captures... although this will depend on what the currently pointless $3 and $8 are supposed to actually be.


First, when learning perl you should always use warnings and use strict.

When you perform a regex match, you are matching substrings within strings, so your matches are strings. However, perl will convert strings to numbers if the context calls for that. For instance, if you write:

$4 - $1

$4 and $1 have to be numbers because there is no - operator for strings, so perl converts the strings $4 and $1 to their numeric equivalents, and then perl performs the subtraction. Similarly, if you write:

$4 == ""

the == operator only operates on numbers, so perl converts $4 to a number---but perl is hesitant to convert "" to a number. If you write a string literal like "dog" or "" in your code where a number is called for, then perl suspects you might have made an error, and use warnings tells perl to alert you to the possible error--instead of just blindly doing the conversion.

To compare strings in perl, you use the eq operator.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜