Я программирую на Perl, время от времени, в течение многих лет, хотя лишь изредка это мой основной язык. Поскольку я часто месяцами не пишу ни одного Perl, я сильно полагаюсь на свою загнутую книгу Camel Book, которая напоминает мне, как что-то делать. Однако, когда я копирую рецепты дословно, ничего не понимая, это меня беспокоит. Это один из самых неприятных моментов: на странице 154 3-го издания Camel есть пример «изменения строк мимоходом», который читается так:
($lotr = $hobbit) =~ s/Bilbo/Frodo/g;
Q1) что здесь происходит? На чем именно работает регулярное выражение?
Q2) Необходим ли этот почти волшебный синтаксис для такой базовой операции, как «взять строку из $ a, изменить ее с помощью регулярного выражения, поместить результат в $ b»?
Q3) Как мне выполнить эту операцию, используя переменную цикла по умолчанию в качестве начальной строки?
Заранее приносим свои извинения тем, кто мечтает о Perl, для которых все вышесказанное выглядит совершенно естественно.





Хммм ... ($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";
}
Интересно, что волшебная переменная $_ не изменяется этой операцией. Вот как вы можете сделать вывод, что присвоение происходит до подстановки регулярного выражения и что подстановка никак не взаимодействует с пространством шаблонов по умолчанию.
А что касается опытных программистов Perl ... Я не знаю слишком много людей, которых бросает в глаза какая-то часть синтаксиса Perl, независимо от того, как долго они на нее пялились, кроме мистера Шварца, конечно;)
@ Д.Шоули. Jees mate. Из того, что вы сказали выше, почему нужно изменить $ _? «скопируйте строку из $ a ($ _) ... в $ b ($ lotr) и измените $ b ($ lotr) с помощью регулярного выражения, поместите результат в $ b ($ lotr)». Никакого волшебства, связанного с $ _.
Спасибо, мистер Шоули. Я много использую IDL, а в IDL нет операторов на месте - все равно $ y = f ($ x). Эта грамматика превратилась в умственную привычку, которая мешала мне грокнуть элементарный Perl. Спасибо за разлочку.
@Rob - хе-хе-хе ... почему-то я всегда ожидаю, что Perl проскальзывает в $_, когда вы не смотрите;)
Разные языки делают разные вещи с оператором присваивания. В некоторых случаях это утверждение, а не выражение, поэтому его нельзя объединить в более крупное выражение. В некоторых случаях он возвращает присвоенное значение, но только как значение (часто называемое 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.
Спасибо, хорошо знать, что синтаксис примера, хотя и не волшебный, специфичен для Perl.
Если во втором квартале вы собираетесь взять подстроку из $ a, вам может пригодиться эта идиома:
($b) = $a =~ /(substring-to-match)/;
$b =~ s/regex-on-susbtring/result-string/;
Также обратите внимание, что $ a и $ b не являются обычными переменными в Perl, поскольку у них есть особые правила области видимости, связанные с функцией сортировки. Подробности смотрите в perldoc perlvar.
Это правильный ответ. Я набирал это, когда это было опубликовано. Это (решение), кстати, заняло у меня один поиск в Google, чтобы найти.