Что действует оператор замещения Perl?
Я программировал в Perl, в течение многих лет, но только спорадически это мой основной язык. Поскольку я часто бываю месяцами без написания perl, я сильно полагаюсь на свою собачью книгу верблюдов, чтобы напомнить мне, как делать что-то. Однако, когда я копирую рецепты дословно без понимания, это беспокоит меня. Это одно из самых неприятных: на странице 154 3-го издания Camel есть пример для "модификации строк en passant, который читается следующим образом:
($lotr = $hobbit) =~ s/Bilbo/Frodo/g;
Q1), что здесь происходит? На чем, собственно, работает регулярное выражение?
Q2) Этот сверхмагический синтаксис необходим для такой базовой операции, как "взять строку из $a, изменить ее с помощью регулярного выражения, поместить результат в $b"?
Q3) Как выполнить эту операцию с использованием переменной по умолчанию цикла в качестве начальной строки?
Извините заблаговременно для мечтателей Perl, для которых это выглядит совершенно естественно.
Ответы
Ответ 1
Хммм... ($lotr=$hobbit) =~ s/Bilbo/Frodo/g
является одним из многих магов Perl. Теперь для некоторых ответов.
Q1) $lotr
присваивается значение, содержащееся в $hobbit
. После назначения мы можем забыть об исходной переменной. Относитесь к ($lotr = $hobbit)
как к собственному утверждению как-если бы мы написали:
$lotr = $hobbit;
$lotr =~ s/Bilbo/Frodo/g;
вместо этого. Регулярное выражение работает на $lotr
.
Q2) Синтаксис - это просто однострочная версия приведенного выше фрагмента. Подумайте об этом как "скопируйте строку из $a
, скопируйте ее в $b
и измените $b
с помощью регулярного выражения" вместо "возьмите строку из $a
, измените ее с помощью регулярного выражения, поместите результат в $b
"
Q3) Я предполагаю, что вы имеете в виду пространство поиска шаблона по умолчанию с помощью "переменной по умолчанию цикла"? В этом случае просто используйте $_
вместо $hobbit
:
while (<>) {
chomp;
($lotr = $_) =~ s/Bilbo/Frodo/g;
print "\$lotr = [$lotr]\n";
print "\$_ = [$_]\n";
}
Интересно, что волшебная переменная var $_
не изменяется этой операцией. Вот как вы можете заключить, что назначение происходит до подстановки регулярных выражений и что подстановка никак не взаимодействует в пространстве шаблонов по умолчанию.
И для опытных программистов Perl... Я не знаю слишком много людей, которые бросают какой-то кусок синтаксиса Perl, независимо от того, как долго они смотрят на него, конечно же, г-н Шварц;)
Ответ 2
Различные языки выполняют разные операции с оператором присваивания. В некоторых это выражение, а не выражение, поэтому не может быть объединено в более крупное выражение. В некоторых случаях он возвращает назначенное значение, но только как значение (часто называемое rvalue), а не как то, что может быть изменено или назначено (lvalue). Примером этого является C, где вы
может написать:
a = b = c; # assign value of c to b and a
но не:
++(b = a); # assign value of a to b, then increment b
И в некоторых случаях результатом присваивания присваивается значение lvalue. (В Perl это относится только к скалярным присваиваниям, назначение списков - более сложный зверь.) Таким образом, вы можете делать ++ ($ b = $a) или ($ b = $a) = ~ s/a/b/или любая другая операция, которая ожидает lvalue при назначении, и сначала выполнит назначение, а затем дополнительно изменит значение lvalue, присвоенное.
Ответ 3
Если в Q2 вы хотите взять подстроку из $a, вы можете найти эту идиому полезной:
($b) = $a =~ /(substring-to-match)/;
$b =~ s/regex-on-susbtring/result-string/;
Также обратите внимание, что $a и $b не являются нормальными переменными в Perl, поскольку у них есть специальные правила области, связанные с функцией сортировки. Подробнее см. "Perldoc perlvar".