Скрытые возможности Perl?
Какие действительно полезные, но эзотерические языковые возможности в Perl вы действительно смогли использовать для выполнения полезной работы?
Методические рекомендации:
- Попробуйте ограничить ответы ядром Perl, а не CPAN
- Пожалуйста, приведите пример и краткое описание
Скрытые функции также можно найти на других языках. Скрытые функции:
(Это все из ответа Кориона)
- С
- Устройство Даффа
- Портативность и стандартность
- C#
- Кавычки для разделенных пробелами списков и строк
- Псевдонимные пространства имен
- Джава
- Статические Инициализаторы
- JavaScript
- Функции являются гражданами первого класса
- Блокировка объема и закрытия
- Вызов методов и методов доступа косвенно через переменную
- Рубин
- Определение методов через код
- PHP
- Распространенная онлайн документация
- Магические методы
- Символические ссылки
- питон
- Обмен значениями одной строки
- Возможность заменить даже основные функции своими собственными функциями
Другие скрытые возможности:
Операторы:
- Квазоператор bool
- Оператор триггера
- Также используется для построения списка
-
++
и одинарный-
операторы работают над строками - Оператор повторения
- Оператор космического корабля
- || оператор (и // оператор), чтобы выбрать из набора вариантов
- Алмазный оператор
- Особые случаи
m//
оператор - Тильда-тильда "оператор"
Цитирование конструкций:
- Оператор qw
- Буквы могут использоваться в качестве разделителей кавычек в конструкциях, подобных q{}
- Механизмы цитирования
Синтаксис и имена:
- После сигил может быть пробел
- Вы можете дать числовые имена с символьными ссылками
- Юридические запятые
- Сгруппированные целочисленные литералы
- ломтики хеша
- Заполнение ключей хеша из массива
Модули, прагмы и параметры командной строки:
- используйте строгие и используйте предупреждения
- Проверка на наличие повреждений
- Эзотерическое использование -n и -p
- CPAN
overload::constant
- IO:: Ручка модуля
- Безопасные отсеки
- Атрибуты
Переменные:
Петли и контроль потока:
Регулярные выражения:
-
\G
якорь (?{})
и '(??{})`в регулярных выражениях
Другие преимущества:
- Отладчик
- Специальные кодовые блоки, такие как BEGIN, CHECK и END
-
DATA
блок - Операции с новым блоком
- Исходные фильтры
- Сигнальные Крючки
- карта ( дважды)
- Обтекание встроенных функций
-
eof
функция -
dbmopen
функция - Превращение предупреждений в ошибки
Другие приемы и мета-ответы:
Смотрите также:
78 ответов
Оператор триггера полезен для пропуска первой итерации при циклическом просмотре записей (обычно строк), возвращаемых дескриптором файла, без использования переменной flag:
while(<$fh>)
{
next if 1..1; # skip first record
...
}
Бежать perldoc perlop
и искать "триггер" для получения дополнительной информации и примеров.
В Perl есть много неочевидных особенностей.
Например, знаете ли вы, что после сигил может быть пробел?
$ perl -wle 'my $x = 3; print $ x'
3
Или, что вы можете дать субсимволы числовые имена, если вы используете символические ссылки?
$ perl -lwe '*4 = sub { print "yes" }; 4->()'
yes
Также есть квазиоператор "bool", который возвращает 1 для истинных выражений и пустую строку для ложных:
$ perl -wle 'print !!4'
1
$ perl -wle 'print !!"0 but true"'
1
$ perl -wle 'print !!0'
(empty line)
Другие интересные вещи: с use overload
Вы можете перегрузить строковые литералы и числа (и, например, сделать их BigInts или что-то еще).
Многие из этих вещей фактически где-то документированы или логически вытекают из документированных функций, но, тем не менее, некоторые из них не очень хорошо известны.
Обновление: еще один приятный. Ниже q{...}
упоминались конструкции цитирования, но знаете ли вы, что вы можете использовать буквы в качестве разделителей?
$ perl -Mstrict -wle 'print q bJet another perl hacker.b'
Jet another perl hacker.
Также вы можете писать регулярные выражения:
m xabcx
# same as m/abc/
Добавить поддержку для сжатых файлов с помощью волшебного ARGV:
s{
^ # make sure to get whole filename
(
[^'] + # at least one non-quote
\. # extension dot
(?: # now either suffix
gz
| Z
)
)
\z # through the end
}{gzcat '$1' |}xs for @ARGV;
(кавычки около $_ необходимы для обработки имен файлов с метасимволами оболочки в)
Теперь <>
функция распакует любой @ARGV
файлы, заканчивающиеся на ".gz" или ".Z":
while (<>) {
print;
}
Одна из моих любимых функций в Perl - использование логического значения ||
Оператор для выбора между набором вариантов.
$x = $a || $b;
# $x = $a, if $a is true.
# $x = $b, otherwise
Это означает, что можно написать:
$x = $a || $b || $c || 0;
принять первое истинное значение из $a
, $b
, а также $c
или по умолчанию 0
иначе.
В Perl 5.10 есть также //
оператор, который возвращает левую часть, если она определена, и правую часть в противном случае. Следующее выбирает первое определенное значение из $a
, $b
, $c
, или же 0
иначе:
$x = $ a // $ b // $ c // 0;
Они также могут использоваться с их сокращенными формами, которые очень полезны для обеспечения значений по умолчанию:
$x || = 0; # Если $x было ложным, теперь оно имеет значение 0. $x // = 0; # Если $x был неопределенным, теперь он имеет значение ноль.
Cheerio,
Павел
Операторы ++ и унарные - работают не только с числами, но и со строками.
my $_ = "a"
print -$_
печатает -a
print ++$_
печатает б
$_ = 'z'
print ++$_
печатает аа
Поскольку в Perl есть почти все "эзотерические" части из других списков, я скажу вам одну вещь, которую Perl не может:
Perl не может использовать голые произвольные URL в вашем коде, потому что //
Оператор используется для регулярных выражений.
На тот случай, если вам неясно, какие функции предлагает Perl, вот выборочный список, возможно, не совсем очевидных записей:
Переносимость и стандартность. Вероятно, с Perl больше компьютеров, чем с компилятором C
Класс манипулирования файлами / путями - File:: Find работает даже в большем количестве операционных систем, чем.Net
Кавычки для списков и строк, разделенных пробелами - Perl позволяет вам выбирать почти произвольные кавычки для вашего списка и разделителей строк
Псевдонимные пространства имен - в Perl они имеют следующие назначения:
*My::Namespace:: = \%Your::Namespace
Статические инициализаторы - Perl может запускать код практически на каждом этапе компиляции и создания объектов, начиная с BEGIN
(разбор кода) для CHECK
(после разбора кода) import
(при импорте модуля) в new
(создание объекта) для DESTROY
(уничтожение объекта) до END
(программа выхода)
Функции являются гражданами первого класса - как в Perl
Область действия и закрытие блока - в Perl есть
Вызов методов и методов доступа косвенно через переменную - это делает Perl:
my $method = 'foo';
my $obj = My::Class->new();
$obj->$method( 'baz' ); # calls $obj->foo( 'baz' )
Определение методов с помощью кода - Perl это тоже позволяет:
*foo = sub { print "Hello world" };
Распространенная онлайн-документация - Perl-документация находится в сети и, вероятно, в вашей системе тоже
Магические методы, которые вызываются при вызове "несуществующей" функции - Perl реализует это в функции AUTOLOAD
Символические ссылки - вам настоятельно рекомендуется держаться подальше от них. Они будут есть твоих детей. Но, конечно же, Perl позволяет предлагать своих детей кровожадным демонам.
Обмен значениями на одну строку - Perl позволяет присваивать списки
Возможность заменить даже основные функции своими собственными функциями
use subs 'unlink';
sub unlink { print 'No.' }
или же
BEGIN{
*CORE::GLOBAL::unlink = sub {print 'no'}
};
unlink($_) for @ARGV
Проще всего процитировать практически любую странную строку в Perl.
my $url = q{http://my.url.com/any/arbitrary/path/in/the/url.html};
На самом деле, различные механизмы цитирования в Perl довольно интересны. Механизмы цитирования в стиле регулярных выражений Perl позволяют вам заключать в кавычки все, указав разделители. Вы можете использовать практически любые специальные символы, такие как #, / или открывать / закрывать символы, такие как (), [] или {}. Примеры:
my $var = q#some string where the pound is the final escape.#;
my $var2 = q{A more pleasant way of escaping.};
my $var3 = q(Others prefer parens as the quote mechanism.);
Механизмы цитирования:
q: буквальная кавычка; единственный символ, который должен быть экранирован, является конечным символом. qq: интерпретируемая цитата; обрабатывает переменные и экранирующие символы. Отлично подходит для строк, которые нужно процитировать:
my $var4 = qq{This "$mechanism" is broken. Please inform "$user" at "$email" about it.};
qx: работает как qq, но затем выполняет ее как системную команду, а не в интерактивном режиме. Возвращает весь текст, сгенерированный из стандарта out. (Перенаправление, если поддерживается в ОС, также выходит) Также сделано с обратными кавычками (символ `).
my $output = qx{type "$path"}; # get just the output
my $moreout = qx{type "$path" 2>&1}; # get stuff on stderr too
qr: интерпретирует как qq, но затем компилирует его как регулярное выражение. Работает с различными опциями в регулярном выражении. Теперь вы можете передать регулярное выражение в качестве переменной:
sub MyRegexCheck {
my ($string, $regex) = @_;
if ($string)
{
return ($string =~ $regex);
}
return; # returns 'null' or 'empty' in every context
}
my $regex = qr{http://[\w]\.com/([\w]+/)+};
@results = MyRegexCheck(q{http://myurl.com/subpath1/subpath2/}, $regex);
qw: очень, очень полезный оператор цитаты. Превращает в кавычки набор слов, разделенных пробелами, в список. Отлично подходит для заполнения данных в модульном тесте.
my @allowed = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z { });
my @badwords = qw(WORD1 word2 word3 word4);
my @numbers = qw(one two three four 5 six seven); # works with numbers too
my @list = ('string with space', qw(eight nine), "a $var"); # works in other lists
my $arrayref = [ qw(and it works in arrays too) ];
Они великолепно используют их, когда это проясняет ситуацию. Для qx, qq и q я, скорее всего, использую операторы {}. Чаще всего люди, использующие qw, обычно используют оператор (), но иногда вы также видите qw//.
Оператор "for" можно использовать так же, как "with" в Pascal:
for ($item)
{
s/ / /g;
s/<.*?>/ /g;
$_ = join(" ", split(" ", $_));
}
Вы можете применить последовательность операций s/// и т. Д. К одной и той же переменной, не повторяя имя переменной.
ПРИМЕЧАНИЕ. В неразрывном пространстве над (& nbsp;) скрыт Unicode, чтобы обойти уценку. Не копируйте, вставьте это:)
Не совсем скрытый, но многие программисты Perl каждый день не знают о CPAN. Это особенно относится к людям, которые не являются программистами на полную ставку или не программируют на Perl.
Возможность разбора данных, непосредственно вставленных в блок данных. Не нужно сохранять тестовый файл для открытия в программе или аналогичном. Например:
my @lines = <DATA>;
for (@lines) {
print if /bad/;
}
__DATA__
some good data
some bad data
more good data
more good data
Оператор цитаты - одна из моих любимых вещей. Для сравнения:
my @list = ('abc', 'def', 'ghi', 'jkl');
а также
my @list = qw(abc def ghi jkl);
Гораздо меньше шума, легче для глаз. Еще одна очень приятная вещь в Perl, которую очень не хватает при написании SQL, это то, что завершающая запятая допустима:
print 1, 2, 3, ;
Это выглядит странно, но не если вы сделаете отступ в коде другим способом:
print
results_of_foo(),
results_of_xyzzy(),
results_of_quux(),
;
Добавление дополнительного аргумента к вызову функции не требует от вас возиться с запятыми в предыдущих или конечных строках. Изменение одной строки не влияет на окружающие линии.
Это делает работу с переменными функциями очень приятной. Это, пожалуй, одна из самых недооцененных возможностей Perl.
Двоичный "х" является оператором повторения:
print '-' x 80; # print row of dashes
Также работает со списками:
print for (1, 4, 9) x 3; # print 149149149
Проверка порчи. При включенной проверке заражения Perl умрет (или предупредит -t
) если вы попытаетесь передать испорченные данные (грубо говоря, данные извне программы) небезопасной функции (открытие файла, выполнение внешней команды и т. д.). Это очень полезно при написании сценариев setuid или CGI, или чего-либо еще, где сценарий обладает большими привилегиями, чем тот, кто передает ему данные.
Волшебный гото. goto &sub
делает оптимизированный хвостовой вызов.
Отладчик
use strict
а также use warnings
, Это может спасти вас от множества опечаток.
Операции с новым блоком
Я бы сказал, что возможность расширения языка, создания псевдоблочных операций - одна из них.
Вы объявляете прототип для подпрограммы, указывающей, что она сначала берет ссылку на код:
sub do_stuff_with_a_hash (&\%) { my ( $block_of_code, $hash_ref ) = @_; while ( my ( $k, $v ) = each %$hash_ref ) { $block_of_code->( $k, $v ); } }
Затем вы можете назвать это в теле так
use Data::Dumper; do_stuff_with_a_hash { local $Data::Dumper::Terse = 1; my ( $k, $v ) = @_; say qq(Hey, the key is "$k"!); say sprintf qq(Hey, the value is "%v"!), Dumper( $v ); } %stuff_for ;
(Data::Dumper::Dumper
это еще одна скрытая жемчужина.) Обратите внимание, что вам не нужно sub
Ключевое слово перед блоком или запятая перед хешем. Это выглядит так: map { } @list
Исходные фильтры
Также есть исходные фильтры. Где Perl передаст вам код, чтобы вы могли им манипулировать. И то, и другое, и операции с блоками, в значительной степени не относятся к типу "не пытайся это дома".
Я сделал несколько полезных вещей с исходными фильтрами, например, создал очень простой язык для проверки времени, позволив коротким однострочникам Perl для принятия решения:
perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';
Lib::TL
будет просто сканировать как "переменные" и константы, создавать их и подставлять их по мере необходимости.
Опять же, исходные фильтры могут быть грязными, но мощными. Но они могут испортить отладчикам что-то ужасное - и даже предупреждения могут быть напечатаны с неправильными номерами строк. Я перестал использовать Damian's Switch, потому что отладчик потерял бы всю способность говорить мне, где я на самом деле был. Но я обнаружил, что вы можете минимизировать ущерб, изменяя небольшие фрагменты кода, сохраняя их в одной строке.
Сигнальные Крючки
Это достаточно часто делается, но не все так очевидно. Вот обработчик кубика, который копилку на старом.
my $old_die_handler = $SIG{__DIE__};
$SIG{__DIE__}
= sub { say q(Hey! I'm DYIN' over here!); goto &$old_die_handler; }
;
Это означает, что всякий раз, когда какой-то другой модуль в коде хочет умереть, он должен прийти к вам (если кто-то другой не сделает деструктивную перезапись на $SIG{__DIE__}
). И вы можете быть уведомлены, что кто-то что-то считает ошибкой.
Конечно, для достаточно вещей вы можете просто использовать END { }
заблокировать, если все, что вы хотите сделать, это очистить.
overload::constant
Вы можете проверять литералы определенного типа в пакетах, которые включают ваш модуль. Например, если вы используете это в своем import
суб:
overload::constant
integer => sub {
my $lit = shift;
return $lit > 2_000_000_000 ? Math::BigInt->new( $lit ) : $lit
};
это будет означать, что каждое целое число больше 2 миллиардов в вызывающих пакетах будет изменено на Math::BigInt
объект. (Смотрите перегрузка:: константа).
Сгруппированные целочисленные литералы
Пока мы на этом. Perl позволяет разбивать большие числа на группы по три цифры и при этом получать из них целое разборное число. Заметка 2_000_000_000
выше за 2 млрд.
На основании того, как "-n"
а также "-p"
Переключатели реализованы в Perl 5, вы можете написать, казалось бы, некорректную программу, в том числе }{
:
ls |perl -lne 'print $_; }{ print "$. Files"'
который конвертируется внутренне в этот код:
LINE: while (defined($_ = <ARGV>)) {
print $_; }{ print "$. Files";
}
Это мета-ответ, но архивы Советов Perl содержат все виды интересных трюков, которые можно сделать с помощью Perl. Архив предыдущих советов доступен для просмотра в Интернете и может быть подписан через список рассылки или атомную ленту.
Некоторые из моих любимых советов включают создание исполняемых файлов с использованием PAR, использование autodie для автоматического генерирования исключений и использование конструкций switch и smart-match в Perl 5.10.
Раскрытие информации: я один из авторов и сопровождающих Perl Tips, так что я, очевидно, очень высоко ценю их.;)
Давайте начнем с оператора космического корабля.
$a = 5 <=> 7; # $a is set to -1
$a = 7 <=> 5; # $a is set to 1
$a = 6 <=> 6; # $a is set to 0
map - не только потому, что он делает код более выразительным, но и потому, что он дал мне импульс прочитать немного больше об этом "функциональном программировании".
Предложение продолжения для циклов. Он будет выполняться в нижней части каждого цикла, даже тех, которые находятся рядом.
while( <> ){
print "top of loop\n";
chomp;
next if /next/i;
last if /last/i;
print "bottom of loop\n";
}continue{
print "continue\n";
}
Мой голос был бы за (?{}) И (??{}) группы в регулярных выражениях Perl. Первый выполняет код Perl, игнорируя возвращаемое значение, второй выполняет код, используя возвращаемое значение в качестве регулярного выражения.
m//
Оператор имеет несколько неясных особых случаев:
- Если вы используете
?
в качестве разделителя он совпадает только один раз, если вы не позвонитеreset
, - Если вы используете
'
в качестве разделителя шаблон не интерполируется. - Если шаблон пуст, он использует шаблон из последнего успешного совпадения.
Алмазный оператор с нулевой файловой ручкой<>
имеет свое место в создании инструментов командной строки. Действует как <FH>
читать из дескриптора, за исключением того, что он волшебным образом выбирает, что будет найдено первым: имена файлов командной строки или STDIN. Взято из перлопа:
while (<>) {
... # code for each line
}
Специальные блоки кода, такие как BEGIN
, CHECK
а также END
, Они происходят из Awk, но в Perl работают иначе, потому что они не основаны на записях.
BEGIN
блок может использоваться для указания некоторого кода для фазы синтаксического анализа; это также выполняется, когда вы делаете проверку синтаксиса и переменных perl -c
, Например, чтобы загрузить переменные конфигурации:
BEGIN {
eval {
require 'config.local.pl';
};
if ($@) {
require 'config.default.pl';
}
}
rename("$_.part", $_) for "data.txt";
переименовывает data.txt.part в data.txt без необходимости повторяться.
Немного неясен "оператор" тильды-тильды, который задает скалярный контекст.
print ~~ localtime;
такой же как
print scalar localtime;
и отличается от
print localtime;
Разделитель входных записей может быть установлен на ссылку на число для чтения записей фиксированной длины:
$/ = \3; print $_,"\n" while <>; # output three chars on each line
Оператор козла*
:
$_ = "foo bar";
my $count =()= /[aeiou]/g; #3
или же
sub foo {
return @_;
}
$count =()= foo(qw/a b c d/); #4
Это работает, потому что назначение списка в скалярном контексте дает количество элементов в списке, который назначается.
*
Обратите внимание, на самом деле не оператор
"Режим отчаяния" конструкций управления циклами Perl, который заставляет их искать в стеке, чтобы найти подходящую метку, допускает некоторые любопытные поведения, которыми пользуется Test::More, к лучшему или к худшему.
SKIP: {
skip() if $something;
print "Never printed";
}
sub skip {
no warnings "exiting";
last SKIP;
}
Там есть малоизвестный файл.pmc. "use Foo" будет искать Foo.pmc в @INC до Foo.pm. Это было сделано для того, чтобы сначала загружать скомпилированный байт-код, но Module::Compile использует это для кэширования исходно отфильтрованных модулей для ускорения загрузки и отладки.
Возможность превращать предупреждения в ошибки.
local $SIG{__WARN__} = sub { die @_ };
$num = "two";
$sum = 1 + $num;
print "Never reached";
Это то, что я могу придумать, не упомянув.