В Perl, что означает if (s/^\+//)?
В коде Perl/Tk я нашел условное выражение, как показано ниже
if (s/^\+//)
{
#do something
}
elsif (/^-/)
{
#do another thing
}
Похоже, какое-то сопоставление с образцом было сделано. Но я не могу этого понять. Может ли кто-нибудь помочь мне понять это сопоставление с образцом?
4 ответа
Они оба регулярные выражения. Вы можете прочитать о них в perlre и perlretut. Вы можете поиграть с ними на http://www.rubular.com/r/CEtqZ3YUIi.
Они оба косвенно делают что-то с $_
, Там, вероятно, есть while
или же foreach
вокруг ваших строк кода без переменной цикла. В таком случае, $_
становится этой переменной цикла. Например, он может содержать текущую строку файла, который читается.
- Если текущее значение
$_
содержит+
(плюс) знак в качестве первого символа в начале строки,#do somehting
, - Иначе, если он содержит
-
(минус) знак,#do another thing
,
В случае 1. это также заменяет +
подписать ни с чем (т.е. удаляет его). Не удаляет -
в 2. однако.
Давайте посмотрим на объяснение с YAPE:: Regex:: Explain.
use YAPE::Regex::Explain;
print YAPE::Regex::Explain->new(qr/^\+/)->explain();
Вот. Не очень полезно в нашем случае, но, тем не менее, хороший инструмент. Обратите внимание, что (?-imsx
а также )
части - это то, что по умолчанию подразумевает Perl. Они всегда рядом, если вы не измените их.
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
----------------------------------------------------------------------
Обновление: Как отметил Mikko L в комментариях, возможно, вам следует реорганизовать / изменить этот фрагмент кода. Хотя он, вероятно, делает то, что должен, я считаю, что было бы неплохо сделать его более читабельным. Кто бы ни написал это, очевидно, не заботился о вас как о более позднем сопровождающем. Я предлагаю вам сделать. Вы можете изменить это на:
# 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
}
Это регулярные выражения, используемые для сопоставления и замены шаблонов.
Вы должны прочитать концепцию, но что касается вашего вопроса:
s/^\+//
Если строка начиналась с плюса, удалите этот плюс ("s" означает "заменить") и верните true.
/^-/
True, если строка начинается с минуса.
Этот код эквивалентен
if ($_ =~ s/^\+//) { # s/// modifies $_ by default
#do something
}
elsif ($_ =~ m/^-/) { # m// searches $_ by default
#do another thing
}
s///
а также m//
являются кавычками операторов регулярного выражения. Вы можете прочитать о них в perlop.
Другие ответы дали краткое изложение того, как работает код, но не так много, почему. Вот простой пример того, почему можно использовать такую логику.
#!/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;
Когда вы называете сценарий как
./test.pl hi nobye
ты получаешь
$VAR1 = {
'hi' => 1,
'bye' => 0
};
Ключом является строка, однако, если ей предшествует no
затем удалите его (чтобы получить рассматриваемый ключ) и вместо этого установите значение 0
,
Пример OP немного сложнее, но следует той же логике.
- если ключ начинается с
+
, удали его и сделай что-нибудь - если ключ начинается с
-
, не удаляй это и делай что-то еще