简体   繁体   中英

In Perl, what is the meaning of if (s/^\+//)?

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?

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.

  1. If the current value of $_ contains a + (plus) sign as the first character at the beginning of the string, #do somehting .
  2. Else if it contains a - (minus) sign, #do another thing .

In case 1. it also replaces that + sign with nothing (ie 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
}

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.

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 .

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.

  • if the key starts with a + , remove it and do something
  • if the key starts with a - , don't remove it and do something else

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM