perltrap
СОДЕРЖАНИЕ
НАЗВАНИЕ
perltrap - Ловушки Perl для неопытных программистов
ОПИСАНИЕ
Самая большая ловушка – забыть use warnings или использовать переключатель -w; см. warnings и "-w" в perlrun. Вторая по значимости ловушка – не сделать весь свой код исполняемым под use strict. Третья по значимости ловушка – не прочитать список изменений в этой версии Perl; см. perldelta.
Ловушки Awk
Пользователи awk должны обратить особое внимание на следующее:
-
Программа Perl выполняется только один раз, а не один раз для каждой строки ввода. Вы можете реализовать неявный цикл с помощью
-nили-p. -
Модуль English, загруженный с помощью
use English;позволяет вам обращаться к специальным переменным (например,
$/) по именам (например, $RS), как будто они находятся в awk; см. perlvar для получения подробностей. -
После всех простых операторов в Perl требуются точки с запятой (кроме конца блока). Перевод строки не является разделителем операторов.
-
Фигурные скобки необходимы для
ifиwhile. -
Переменные в Perl начинаются с "$", "@" или "%".
-
Индексы массивов начинаются с 0. Аналогично для позиций строк в substr() и index().
-
Вам необходимо определить, используете ли вы в массиве числовые или строковые индексы.
-
Значения хэшей не появляются при простом обращении к ним.
-
Вам необходимо определить, хотите ли вы использовать строковые или числовые сравнения.
-
Чтение строки ввода не разбивает её за вас. Вы сами должны разбить её на массив. А оператор split() имеет разные аргументы, чем в awk.
-
Текущая строка ввода обычно хранится в $_, а не в $0. Обычно она не лишена символа новой строки. ($0 – это имя исполняемой программы.) См. perlvar.
-
$<цифра> не относится к полям – оно относится к подстрокам, совпадающим с последним шаблоном совпадения.
-
Оператор print() не добавляет разделители полей и записей, если вы не зададите
$,и$\. Вы можете задать $OFS и $ORS, если используете модуль English. -
Вы должны открыть ваши файлы перед записью в них.
-
Оператор диапазона – это "..", а не запятая. Оператор запятой работает, как в C.
-
Оператор совпадения – это "=~", а не "~". ("~" – это оператор дополнения, как в C.)
-
Оператор возведения в степень – это "**", а не "^". "^" – это оператор XOR, как в C. (У вас может сложиться впечатление, что awk по своей сути несовместим с C.)
-
Оператор конкатенации – это ".", а не пустая строка. (Использование пустой строки сделало бы
/pat/ /pat/неразборчивым, так как третий слэш интерпретировался бы как оператор деления — лексический анализатор фактически немного чувствителен к контексту для операторов, таких как "/", "?", и ">". И, в действительности, сам "." может быть началом числа.) -
Ключевые слова
next,exit, иcontinueработают по-другому. -
Следующие переменные работают по-другому:
Awk Perl ARGC scalar @ARGV (compare with $#ARGV) ARGV[0] $0 FILENAME $ARGV FNR $. - something FS (whatever you like) NF $#Fld, or some such NR $. OFMT $# OFS $, ORS $\ RLENGTH length($&) RS $/ RSTART length($`) SUBSEP $; -
Вы не можете установить $RS в шаблон, только в строку.
-
В случае сомнений, запустите конструкцию awk через a2p и посмотрите, что вы получите.
Ловушки C/C++
Программисты, хорошо разбирающиеся в C и C++, должны обратить внимание на следующее:
-
Фигурные скобки необходимы для
ifиwhile. -
Вы должны использовать
elsifвместоelse if. -
Ключевые слова
breakиcontinueиз C становятся в Perllastиnext, соответственно. В отличие от C, они не работают внутри конструкцииdo { } while. См. "Управление циклами" в perlsyn. -
Оператор switch называется
given/whenи доступен только в perl 5.10 и более поздних версиях. См. "Операторы switch" в perlsyn. -
Переменные в Perl начинаются с "$", "@" или "%".
-
Комментарии начинаются с "#", а не "/*" или "//". Perl может интерпретировать комментарии C/C++ как операторы деления, незавершенные регулярные выражения или оператор "определённо или".
-
Вы не можете получить адрес чего-либо, хотя похожим оператором в Perl является обратный слэш, который создаёт ссылку.
-
ARGVдолжно быть написано с большой буквы.$ARGV[0]– этоargv[1]в C, аargv[0]превращается в$0. -
Системные вызовы, такие как link(), unlink(), rename() и т. д., возвращают ненулевое значение для успеха, а не 0. (system(), однако, возвращает ноль для успеха.)
-
Обработчики сигналов работают с именами сигналов, а не с номерами. Используйте
kill -lдля поиска их названий на вашей системе.
Ловушки JavaScript
Программисты, хорошо разбирающиеся в JavaScript, должны обратить внимание на следующее:
-
В Perl двоичная
+всегда представляет сложение.$string1 + $string2преобразует обе строки в числа и затем складывает их. Для конкатенации двух строк используйте оператор.. -
Унарный оператор
+ничего не делает в Perl. Он существует, чтобы избежать синтаксических неоднозначностей. -
В отличие от
for...in,for(также пишетсяforeach) Perl не позволяет левой части быть произвольным выражением. Она должна быть переменной:for my $variable (keys %hash) { ... }Кроме того, не забудьте про
keysтам, так какforeach my $kv (%hash) {}проходит по ключам и значениям и обычно бесполезен ($kv – это ключ, затем значение и так далее). -
Чтобы перебирать индексы массива, используйте
foreach my $i (0 .. $#array) {}.foreach my $v (@array) {}перебирает значения. -
Perl требует фигурных скобок после
if,while,foreach, и т.д. -
В Perl
else ifпишется какelsif. -
? :имеет более высокий приоритет, чем присваивание. В JavaScript можно написать:condition ? do_something() : variable = 3и переменная присваивается только если условие ложно. В Perl вам нужны скобки:
$condition ? do_something() : ($variable = 3);Или просто используйте
if. -
Perl требует точек с запятой для разделения операторов.
-
Переменные, объявленные с
myвлияют только на код после объявления. Вы не можете написать$x = 1; my $x;и ожидать, что первое присваивание повлияет на ту же переменную. Вместо этого оно присвоит значение переменной, объявленной ранее во внешнем пространстве имён, или глобальной переменной.Также обратите внимание, что переменная не становится видимой до следующего оператора. Это означает, что в
my $x = 1 + $xвторой $x относится к той, что была объявлена ранее. -
Переменные
myограничены текущим блоком, а не текущей функцией. Если вы напишете{my $x;} $x;, второй$xне относится к объявленной внутри блока. -
Члены объекта не могут быть доступны как переменные. Ближайший эквивалент Perl для
with(object) { method() }– этоfor, который может быть синонимом$_для объекта:for ($object) { $_->method; } -
Объект или класс, к которому применяется метод, передаётся как один из аргументов метода, а не как отдельное значение
this.
Ловушки Sed
Опытные программисты sed должны обратить внимание на следующее:
-
Программа Perl выполняется только один раз, а не один раз для каждой строки ввода. Вы можете реализовать неявный цикл с помощью
-nили-p. -
Обратные ссылки в заменах используют "$" вместо "\".
-
Метасимволы совпадения шаблонов "(", ")", и "|" не имеют обратных слэшей перед собой.
-
Оператор диапазона – это
..., а не запятая.
Ловушки оболочки
Опытные программисты оболочек должны обратить внимание на следующее:
-
Оператор обратных кавычек выполняет интерполяцию переменных без учёта наличия одинарных кавычек в команде.
-
Оператор обратных кавычек не выполняет преобразование возвращаемого значения, в отличие от csh.
-
Оболочки (особенно csh) выполняют несколько уровней подстановок для каждой строки команды. Perl выполняет подстановки только в определённых конструкциях, таких как двойные кавычки, обратные кавычки, угловые скобки и шаблоны поиска.
-
Оболочки интерпретируют скрипты понемногу. Perl компилирует всю программу перед её выполнением (кроме блоков
BEGIN, которые выполняются во время компиляции). -
Аргументы доступны через @ARGV, а не $1, $2 и т.д.
-
Переменная окружения не предоставляется автоматически как отдельные скалярные переменные.
-
Оболочечный
testиспользует "=", "!=", "<" и т.д. для сравнения строк и "-eq", "-ne", "-lt" и т.д. для сравнения чисел. Это обратная ситуация с Perl, в котором используютсяeq,ne,ltдля сравнения строк и==,!=<и т.д. для сравнения чисел.
Ловушки Perl
Опытные программисты Perl должны обратить внимание на следующее:
-
Помните, что многие операции ведут себя по-разному в контексте списка, чем в скалярном. Подробности см. в perldata.
-
Избегайте "barewords", если можете, особенно полностью строчные. Вы не можете определить по внешнему виду, является ли "bareword" функцией или строкой. Используя кавычки для строк и скобки для вызовов функций, вы никогда не перепутаете их.
-
Вы не можете определить на первый взгляд, какие встроенные функции являются унарными операторами (например, chop() и chdir()), а какие — операторами списка (например, print() и unlink()). (Если не прототипированы, пользовательские подпрограммы могут только быть операторами списка, но никогда унарными.) См. perlop и perlsub.
-
Люди с трудом запоминают, что некоторые функции по умолчанию используют $_, или @ARGV, или что-то другое, но другие, которые вы могли бы ожидать, — нет.
-
Конструкт <FH> не является именем дескриптора файла, это операция readline для этого дескриптора. Прочитанные данные присваиваются $_ только в том случае, если чтение файла является единственным условием в цикле while:
while (<FH>) { } while (defined($_ = <FH>)) { }.. <FH>; # data discarded! -
Помните, что не следует использовать
=когда вам нужно=~; эти два конструкта довольно разные:$x = /foo/; $x =~ /foo/; -
Конструкт
do {}— это не настоящий цикл, на котором можно использовать управление циклом. -
Используйте
my()для локальных переменных всякий раз, когда это возможно (но см. perlform в тех случаях, когда это невозможно). Использованиеlocal()фактически присваивает локальное значение глобальной переменной, что открывает вам возможность непредвиденных побочных эффектов динамического области видимости. -
Если вы локализуете экспортируемую переменную в модуле, её экспортированное значение не изменится. Локальное имя становится псевдонимом нового значения, но внешнее имя по-прежнему является псевдонимом оригинального.
Как всегда, если что-либо из этого когда-либо будет официально объявлено ошибкой, это будет исправлено и удалено.
© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.34.0/perltrap