Reputation: 401
In a Perl/Tk code I found a conditional statement as below
if (s/^\+//)
{
#do something
}
elsif (/^-/)
{
#do another thing
}
Seems like some pattern matching has been done. But I cannot understand it. Can anyone help me understanding this pattern matching?
Upvotes: 2
Views: 4233
Reputation: 20280
The other answers have given a summary of how the code works, but not much of why. Here is a simple example of why one might use such logic.
#!/usr/bin/env perl
use strict;
use warnings;
my $args = {};
for ( @ARGV ) {
if ( s/^no// ) {
$args->{$_} = 0;
} else {
$args->{$_} = 1;
}
}
use Data::Dumper;
print Dumper $args;
When you call the script like
./test.pl hi nobye
you get
$VAR1 = {
'hi' => 1,
'bye' => 0
};
The key is the string, however if it is preceded by no
then remove it (to get the key in question) and instead set the value to 0
.
The OP's example is a little more involved, but follows the same logic.
+
, remove it and do something-
, don't remove it and do something elseUpvotes: 2
Reputation: 54373
They are both regular expressions. You can read up on them at perlre and perlretut. You can play around with them on http://www.rubular.com.
They both implicitly do something with $_
. There probably is a while
or foreach
around your lines of code without a loop variable. In that case, $_
becomes that loop variable. It might for instance contain the current line of a file that is being read.
$_
contains a +
(plus) sign as the first character at the beginning of the string, #do somehting
. -
(minus) sign, #do another thing
. In case 1. it also replaces that +
sign with nothing (i.e. removes it). It does not remove the -
in 2. however.
Let's look at an explanation with YAPE::Regex::Explain.
use YAPE::Regex::Explain;
print YAPE::Regex::Explain->new(qr/^\+/)->explain();
Here it is. Not really helpful in our case, but a nice tool nonetheless. Note that the (?-imsx
and )
parts are the default things Perl implies. They are always there unless you change them.
The regular expression:
(?-imsx:^\+)
matches as follows:
NODE EXPLANATION
----------------------------------------------------------------------
(?-imsx: group, but do not capture (case-sensitive)
(with ^ and $ matching normally) (with . not
matching \n) (matching whitespace and #
normally):
----------------------------------------------------------------------
^ the beginning of the string
----------------------------------------------------------------------
\+ '+'
----------------------------------------------------------------------
) end of grouping
----------------------------------------------------------------------
Update: As Mikko L in the comments pointed out, you should maybe refactor/change this piece of code. While it probably does what it is supposed to, I believe it would be a good idea to make it more readable. Whoever wrote it obviously didn't care about you as the later maintainer. I suggest you do. You could change it to:
# look at the content of $_ (current line?)
if ( s/^\+// )
{
# the line starts with a + sign,
# which we remove!
#do something
}
elsif ( m/^-/ )
{
# the line starts witha - sign
# we do NOT remove the - sign!
#do another thing
}
Upvotes: 12
Reputation: 150021
This code is equivalent to
if ($_ =~ s/^\+//) { # s/// modifies $_ by default
#do something
}
elsif ($_ =~ m/^-/) { # m// searches $_ by default
#do another thing
}
s///
and m//
are regexp quote-like operators. You can read about them in perlop.
Upvotes: 3
Reputation: 262734
Those are regular expressions, used for pattern matching and substitution.
You should read up on the concept, but as for your question:
s/^\+//
If the string started with a plus, remove that plus (the "s" means "substitute"), and return true.
/^-/
True if the string starts with a minus.
Upvotes: 5