Скрытые возможности Perl?

143

Какие действительно полезные, но эзотерические языковые возможности в Perl вы действительно смогли использовать для выполнения полезной работы?

Руководящие указания:

  • Попробуйте ограничить ответы ядром Perl, а не CPAN
  • Пожалуйста, приведите пример и краткое описание

Скрытые функции также можно найти на других языках. Скрытые функции:

(Это все из ответа Кориона )

  • С
    • Устройство Даффа
    • Портативность и стандартность
  • C #
    • Кавычки для разделенных пробелами списков и строк
    • Псевдонимные пространства имен
  • Ява
    • Статические Инициализаторы
  • JavaScript
    • Функции являются гражданами первого класса
    • Блокировка объема и закрытия
    • Вызов методов и методов доступа косвенно через переменную
  • Рубин
    • Определение методов через код
  • PHP
    • Распространенная онлайн документация
    • Магические методы
    • Символические ссылки
  • питон
    • Обмен значениями одной строки
    • Возможность заменить даже основные функции своими собственными функциями

Другие скрытые возможности:

Операторы:

Цитирование конструкций:

Синтаксис и имена:

Модули, прагмы и параметры командной строки:

Переменные:

Петли и контроль потока:

Регулярные выражения:

Другие свойства:

Другие приемы и мета-ответы:


Смотрите также:

Adam Bellaire
источник
Большинство из этих функций используются каждый день, некоторые встречаются в большинстве сценариев Perl, и большинство из них, перечисленных в разделе «Другое», по-прежнему основаны на других языках, поэтому эти «скрытые» изменяют смысл вопроса.
reinierpost

Ответы:

54

Оператор триггера полезен для пропуска первой итерации при циклическом просмотре записей (обычно строк), возвращаемых дескриптором файла, без использования переменной flag:

while(<$fh>)
{
  next if 1..1; # skip first record
  ...
}

Запустите perldoc perlopи найдите «flip-flop» для получения дополнительной информации и примеров.

Джон Сиракуза
источник
На самом деле это взято из Awk, где вы можете сделать триггер между двумя паттернами, написав pattern1, pattern2
Bruno De Fraine
15
Чтобы уточнить, «скрытый» аспект этого заключается в том, что если любой операнд для скалярного «..» является константой, значение неявно сравнивается с номером строки ввода ($.)
Майкл Карман,
47

В 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/
moritz
источник
2
«Знаете ли вы, что после сигил может быть пробел?» Я совершенно ошеломлен. Вот это да.
Аристотель Пагальцис
1
Прохладно! !! $ undef_var не создает предупреждение.
Axeman
4
Я думаю, что вашим примером использования букв для разделения строк должно быть « Просто еще один Perl-хакер», а не «Jet другого Perl-хакера» = P
Крис Латс
Хуже всего то, что вы можете использовать и другие вещи в качестве разделителей. Даже закрывающие скобки. Допустимы следующие: s} regex} replace} xsmg; q] строковый литерал];
Райан Томпсон
46

Добавить поддержку для сжатых файлов через магический 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;
}
тимкай
источник
2
Я не думаю, что вам нужно избегать |замены.
Крис Латс
Я смотрю на это и не могу понять, как это работает. В какой момент zcat |анализируется как команда для прохождения?
эфир
1
@Ether => обнаружение каналов - это функция открытого аргумента с двумя аргументами, которую алмазный оператор использует при открытии каждого файла@ARGV
Eric Strom
40

Одной из моих любимых функций в 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,

Павел

pjf
источник
4
Это настолько распространенная идиома, что она вряд ли может рассматриваться как «скрытая» особенность.
Майкл Карман
3
позор, что симпатичный принтер думает // это комментарий :)
Джон Фергюсон
2
Вопрос, есть ли «функция использования» для использования этих новых операторов или они включены по умолчанию? Я все еще использую возможности Perl 5.10.
JJ
6
// там по умолчанию, никаких специальных настроек не требуется. Вы также можете перенести его в 5.8.x с помощью dor-patch ... см. Каталог авторов / id / H / HM / HMBRAND / на любом зеркале CPAN. FreeBSD 6.x и выше делает это для вас в своем пакете perl.
dland
2
Когда || или // комбинируется с do {}, вы можете инкапсулировать более сложное присваивание, то есть $ x = $ a || do {my $ z; 3 или 4 строки деривации; $ z};
RET
39

Операторы ++ и унарные - работают не только с числами, но и со строками.

my $_ = "a"
print -$_

печатает -a

print ++$_

печатает б

$_ = 'z'
print ++$_

печатает аа

Леон Тиммерманс
источник
3
Процитируем perlvar: «Оператор автоматического декремента не волшебен». Так --что не работает на струнах.
Мориц
«аа» не кажется естественным элементом, следующим за «z». Я ожидал бы следующее самое высокое значение ascii, которое является "{".
Ether
4
Не спрашивайте программиста, что следует за "z"; спроси человека. Эта функция отлично подходит для нумерации элементов в длинном списке.
Барри Браун
17
Когда я был новичком в Perl, я сам реализовал эту функцию с точным поведением z to aa, а затем показал ее коллеге, который посмеялся и мне, и сказал: «позвольте мне показать вам кое-что». Я немного заплакал, но кое-чему научился.
Копас
2
@Ether - если вы хотите, используйте числа и автоматически конвертируйте их в ASCII ord(). Или напишите небольшой класс и перегрузите операторы, чтобы сделать это за вас.
Крис Латс
36

Поскольку в Perl есть почти все «эзотерические» части из других списков, я скажу вам одну вещь, которую Perl не может:

Единственное, чего не может сделать Perl, - это иметь в своем коде произвольные URL-адреса, потому что //оператор используется для регулярных выражений.

На тот случай, если вам неясно, какие функции предлагает Perl, вот выборочный список, возможно, не совсем очевидных записей:

Устройство Даффа - в Perl

Переносимость и Стандартность - Есть , вероятно , больше компьютеров с Perl , чем с компилятором

Класс манипулирования файлами / путями - 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
Corion
источник
Я фанат документации Perl по сравнению с другими языками, но я все еще думаю, что для регулярных выражений и ссылок это можно было бы рационализировать в целом. Например, лучший пример для регулярных выражений - не Perlre, а Perlop
Джон Фергюсон
9
«Единственное, чего не может сделать Perl, - это иметь произвольные произвольные URL в вашем коде, потому что оператор // используется для регулярных выражений». - это полная чушь.
Спасибо за вашу проницательность. Я рассмотрел некоторые способы иметь голый URL-адрес http: // ... в коде Perl без использования фильтра исходного кода и не нашел пути. Может, вы покажете, как это возможно? // используется для регулярных выражений в версиях Perl до 5.8.x. В 5.10 он повторно используется для заданного или присвоения.
Корион
8
Зачем / где вы хотели бы голые URL в вашем коде? Я не могу придумать пример.
Отпуск
18
Никто не хотел бы этого, это просто мем на Java. « foo.com » - это метка http: а затем «foo.com» в комментарии. Некоторые люди находят это интересным, потому что ... они тупые.
jrockway
35

Автовивификация . AFAIK ни на одном другом языке его нет .

JJ
источник
Я понятия не имел, что Python и др. Не поддерживают это.
skiphoppy
@davidnicol: Действительно? Можете ли вы предоставить ссылку? Мой быстрый поиск в Google ничего не дал. Для тех, кто не знает, ECMAscript - правильное имя для Javascript. en.wikipedia.org/wiki/ECMAScript
JJ
1
И есть модуль для отключения автовивации
Александр Черный
1
@Gregg Lind - Учитывая, что Python автоматически создает переменные всякий раз, когда вы впервые назначаете их, автовивификация создаст чудовищные проблемы из-за одной опечатки.
Крис Латс
3
@tchrist - a = [[x * y для y в xrange (1,11)] для x в xrange (1,11)]
Всемогущий
31

Проще всего процитировать почти любую странную строку в 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 //.

Robert P
источник
1
Я иногда использую qw "", чтобы подсветка синтаксиса подсветила его правильно.
Брэд Гилберт
У меня работает в SlickEdit. :)
Роберт П
1
@fengshaun, редакторы, которые я обычно использую , выделяют их правильно. Я имел в виду, частично, подсветку синтаксиса в StackOverflow.
Брэд Гилберт
@Brad Gilbert: Переполнение стека не может (ну, не делает) анализ Perl, который стоит приседать. ☹
tchrist
my $moreout = qx{type "$path" 2>&1};... Я не знал, что ты мог сделать это! [TM]
dland
27

Не совсем скрытый, но многие программисты Perl каждый день не знают о CPAN . Это особенно относится к людям, которые не являются программистами на полную ставку или не программируют на Perl.

mpeters
источник
27

Оператор «for» можно использовать так же, как «with» в Pascal:

for ($item)
{
    s/&‎nbsp;/ /g;
    s/<.*?>/ /g;
    $_ = join(" ", split(" ", $_));
}

Вы можете применить последовательность операций s /// и т. Д. К одной и той же переменной, не повторяя имя переменной.

ПРИМЕЧАНИЕ. В неразрывном пространстве над (& nbsp;) скрыт Юникод, чтобы обойти уценку. Не копируйте, вставьте это :)

тимкай
источник
И "map" тоже делает то же самое ... map {....} $ item; Одним из преимуществ использования «для» над «картой» будет то, что вы можете использовать «Далее», чтобы выйти.
Draegtun
2
Кроме того, для элемента, которым манипулируют, перечисляется перед выполнением манипуляции с кодом, что приводит к лучшей читаемости.
Роберт П,
@RobertP: Это совершенно верно. Актуализатор полезен в дискурсе.
2010 года
26

Оператор цитаты - одна из моих любимых вещей. Для сравнения:

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.

dland
источник
2
Интересный случай синтаксиса Perl заключается в том, что справедливо следующее: для $ _ qw (список вещей) {...}
ephemient
1
Вы можете даже злоупотреблять синтаксисом glob для цитирования слов, если вы не используете специальные символы, такие как * ?. Таким образом, вы можете написатьfor (<a list of stuff>) { ... }
Мориц
1
@ephemient: почти. Это работает только с лексическими выражениями: для моего $ x qw (abc) {...} Например: для $ _ qw (abc) {print} # ничего не печатается
dland
зачем добавлять это лишнее лексическое, когда вы можете наслаждаться любимым по умолчанию Perl? for (qw / abcd /) {print; }
fengshaun
2
@ephemient, @fengshaun, @moritz, @dland: это «исправлено» в blead ; посмотрите эту ветку p5p .
2010 года
26

Возможность синтаксического анализа данных непосредственно вставить в DATA блока. Нет необходимости сохранять в тестовый файл, который будет открыт в программе или аналогичном. Например:

my @lines = <DATA>;
for (@lines) {
    print if /bad/;
}

__DATA__
some good data
some bad data
more good data 
more good data 
аллан
источник
И очень полезно в маленьких тестах!
fengshaun
@peter mortensen, как бы вы имели несколько блоков? И как вы заканчиваете блок?
жаба
@Toad: это ответ Аллана (см. Список редакций). Лучше обратиться к этому пользователю. Или, поскольку этот пользователь оставил переполнение стека, возможно, не обращался ни к кому конкретно (таким образом, настоящий эксперт по Perl может исправить это позже).
Питер Мортенсен
3
@ Хай: Нет, это не уродливо - на самом деле, это как раз противоположность уродливости: она чистая, стройная, минимальная и красивая; Одним словом, это прекрасно, а языки без него - это PITA. @peter mortensen, @toad: Один из ответов на то, как использовать несколько блоков данных в одной программе, - это использовать модуль Inline :: Files из CPAN.
2010 года
Inline :: Files реализован с использованием исходных фильтров. Также есть Data :: Section, который предоставляет несколько встроенных блоков и не использует исходные фильтры.
Пракаш К
24

Операции с новым блоком

Я бы сказал, что возможность расширения языка, создание псевдоблочных операций - одна из них.

  1. Вы объявляете прототип для подпрограммы, указывающей, что она сначала берет ссылку на код:

    sub do_stuff_with_a_hash (&\%) {
        my ( $block_of_code, $hash_ref ) = @_;
        while ( my ( $k, $v ) = each %$hash_ref ) { 
            $block_of_code->( $k, $v );
        }
    }
  2. Затем вы можете назвать это в теле так

    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 млрд.

Axeman
источник
5
При использовании обработчиков $ SIG { DIE } настоятельно рекомендуется проверить $ ^ S, чтобы увидеть, действительно ли ваша программа умирает или просто выдает исключение, которое будет перехвачено. Обычно вы не хотите вмешиваться в последнее.
PJF
Новый блок очень поучителен! Я думал, что это была языковая семантика! большое спасибо.
ZeroCool
Поучительным использованием исходного фильтра является NiceSlice pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ), так что вам не нужно использовать ->sliceметод как каждый раз, когда требуется срез.
Джоэл Бергер
24

Двоичный «х» является оператором повторения :

print '-' x 80;     # print row of dashes

Также работает со списками:

print for (1, 4, 9) x 3; # print 149149149
Bruno De Fraine
источник
Это одна из причин, почему Perl был так популярен среди хакеров. perl -e 'print 0x000 x 25';
JJ
4
Мое любимое использование для этого - создание заполнителей для последней части оператора SQL INSERT: @p = ('?') X $ n; $ p = join (",", @p); $ sql = "INSERT ... VALUES ($ p)";
skiphoppy
24

Проверка порчи. С включенной проверкой заражения perl умрет (или предупредит, с -t), если вы попытаетесь передать испорченные данные (грубо говоря, данные извне программы) небезопасной функции (открытие файла, выполнение внешней команды и т. Д.). Это очень полезно при написании сценариев setuid или CGI, или чего-либо еще, где сценарий обладает большими привилегиями, чем тот, кто передает ему данные.

Волшебный гото. goto &subделает оптимизированный хвостовой вызов.

Отладчик

use strictи use warnings. Это может спасти вас от множества опечаток.

Glomek
источник
1
Почему другие языки не имеют этой функции? Эта функция делает веб-сценарии perl на порядок более безопасными.
Мэтью Локк
22

Основываясь на то , как "-n"и "-p"коммутаторы реализованы в Perl 5, вы можете написать первый взгляд неправильную программу , включающую }{:

ls |perl -lne 'print $_; }{ print "$. Files"'

который конвертируется внутренне в этот код:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}
сек
источник
@martin clayton: Почему это так называется?
2010 года
@ tchrist - потому что он, якобы, похож на двух людей, потирающих носы. В профиле, если вы понимаете, о чем я.
Мартин Клейтон
18

Давайте начнем с оператора космического корабля .

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0
Sec
источник
1
@Leon: C / C ++ не возвращает значения 3 для чисел. Если память выполняет функции String, то единственные 3 возвращаемых значения, которые я знаю на всем языке STL. AFAIK Python не имеет 3-х числовое сравнение. В Java также нет 3-го обратного сравнения.
JJ
7
Стоит упомянуть, что такого полезного в операторах сравнения -1/0/1, поскольку не все могут знать: вы можете связать их вместе с оператором or для выполнения первичных / вторичных / и т.д. сорта. Так что ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)сортирует людей по фамилиям, но если два человека имеют одинаковую фамилию, то они будут заказаны по имени.
Хоббс
@JJ Python имеет 3-значное сравнение: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
букзор
18

Это мета-ответ, но архивы Советов Perl содержат все виды интересных трюков, которые можно сделать с помощью Perl. Архив предыдущих советов доступен для просмотра в Интернете и может быть подписан через список рассылки или атомную ленту.

Некоторые из моих любимых советов включают создание исполняемых файлов с использованием PAR , использование autodie для автоматического генерирования исключений и использование конструкций switch и smart-match в Perl 5.10.

Раскрытие информации: я один из авторов и сопровождающих Perl Tips, так что я, очевидно, очень высоко ценю их. ;)

PJF
источник
2
Вероятно, это один из лучших документированных языков, и он задает шаблон для инструментов для поиска документации. Что список в этом вопросе, вероятно, не так необходим, как для других языков.
Axeman
1
Autodie выглядит очень красиво.
j_random_hacker
18

map - не только потому, что он делает код более выразительным, но и потому, что он дал мне импульс прочитать немного больше об этом «функциональном программировании».

brunorc
источник
15

Предложение продолжения для циклов. Он будет выполняться в нижней части каждого цикла, даже тех, которые находятся рядом.

while( <> ){
  print "top of loop\n";
  chomp;

  next if /next/i;
  last if /last/i;

  print "bottom of loop\n";
}continue{
  print "continue\n";
}
Шон Х Кори
источник
15

Мой голос был бы за (? {}) И (?? {}) группы в регулярных выражениях Perl. Первый выполняет код Perl, игнорируя возвращаемое значение, второй выполняет код, используя возвращаемое значение в качестве регулярного выражения.

Леон Тиммерманс
источник
Perl изобрел так много расширений регулярных выражений, что другие программы теперь часто используют pcre (регулярные выражения, совместимые с perl) вместо исходного языка регулярных выражений.
Sec
Прочитайте небольшую рекламу здесь perldoc.perl.org/… :-D
JJ
Perl действительно (насколько я знаю) возглавляет пакет, когда дело доходит до регулярных выражений.
Брэд Гилберт
Насколько я знаю, это все еще экспериментально и может не сработать так же в будущих Perls. Нельзя сказать, что это бесполезно, но чуть более безопасную и столь же полезную версию можно найти в флаге s /// команды / e: s/(pattern)/reverse($1);/ge;# меняет все patterns.
Крис Латс
@Chris Lutz, @Leon Timmerman: Обратите внимание, что эти две конструкции теперь повторно вводятся. Также обратите внимание, что второй больше не нужно использовать для создания рекурсивных паттернов, теперь мы можем использовать рекурсивные группы. @Brad Gilbert: Правильно, хотя PCRE неплохо отслеживает нас; одна из областей превосходства регулярных выражений, в которой Perl совершенно не подвергается сомнению, - это доступ к свойствам Unicode; видеть мое unitrio распределения uninames, unicharsи особенно unipropsвидеть только часть того , что я имею в виду.
2010 года
13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

Якорь \ G. Это горячее .

JJ
источник
3
... и это указывает на позицию конца предыдущего матча.
Дейв Шерохман
1
Но вы должны называть свое регулярное выражение в скалярном контексте.
Давидникол
@davidnicol: приведенный выше код работает. Можете ли вы уточнить, что вы имеете в виду?
JJ
13

У m//оператора есть несколько неясных особых случаев:

  • Если вы используете ?в качестве разделителя, он совпадает только один раз, если вы не позвоните reset.
  • Если вы используете 'в качестве разделителя, шаблон не интерполируется.
  • Если шаблон пуст, он использует шаблон из последнего успешного совпадения.
Michael Carman
источник
2
Это больше похоже на скрытые ошибки, чем на скрытые возможности! Я не знаю никого, кто любит их. Поток на p5p некоторое время назад обсуждал полезность предполагаемого флага m / $ foo / r, где / r означало бы отсутствие интерполяции (буква не важна), так как никто никогда не помнит вещь с одиночными кавычками.
dland
2
@Dland: Согласен; Я бы назвал эти функции скрытыми ошибками и никогда не использовал бы их в производственном коде.
Майкл Карман
7
Я не могу представить, чтобы Perl-программист не мог запомнить (или даже догадаться), что одинарные кавычки не означают интерполяции. Его использование с этой семантикой является почти универсальным языком , который я предпочел бы ожидать , что это буду так ...
Сундар - восстановит Моника
и если шаблон пустой и последнее успешное совпадение было скомпилировано с модификатором / o, то с этого момента он будет привязан к этому шаблону.
Давидникол
1
Я думаю, что поведение пустого шаблона устарело. Прежде всего потому, что шаблон типа m / $ foo / становится неприятной ошибкой, когда $ foo пуст.
Мэтью S
12

Нулевой указатель_на_файл оператор алмаза <> имеет свое место в создании инструментов командной строки. Он действует как <FH>чтение из дескриптора, за исключением того, что он волшебным образом выбирает, что будет найдено первым: имена файлов командной строки или STDIN. Взято из перлопа:

while (<>) {
...         # code for each line
}
spoulson
источник
4
Он также следует семантике UNIX использования «-» для обозначения «чтения из stdin». Таким образом, вы можете сделать это perl myscript.pl file1.txt - file2.txt, и Perl обработает первый файл, затем stdin, затем второй файл.
Ryan C. Thompson,
Вы можете оператор собственных объектов ( ) для работы как итератор. Однако это не работает, как вы могли ожидать в контексте списка. overload<><$var>
дольмен
11

Специальные блоки кода , такие как BEGIN, CHECKи END. Они приходят из Awk, но в Perl работают иначе, потому что они не основаны на записях.

BEGINБлок может быть использован для указания код для фазы синтаксического анализа; это также выполняется, когда вы делаете проверку синтаксиса и переменной perl -c. Например, чтобы загрузить переменные конфигурации:

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ($@) {
        require 'config.default.pl';
    }
}
Бруно Де Фрейн
источник
11
rename("$_.part", $_) for "data.txt";

переименовывает data.txt.part в data.txt без необходимости повторяться.

timkay
источник
10

Немного неясен «оператор» тильды-тильды, который вызывает скалярный контекст.

print ~~ localtime;

такой же как

print scalar localtime;

и отличается от

print localtime;
Sec
источник
5
Это особенно непонятно, потому что perl5.10.0 также вводит «оператор интеллектуального сопоставления» ~~, который может выполнять сопоставление с регулярным выражением, может проверять, содержится ли элемент в массиве и так далее.
Мориц
Это не неясно, это запутано (и полезно для гольфа и JAPH).
Майкл Карман
Это не правильно! ~~ не безопасно на ссылках! Это приводит их в соответствие.
Леон Тиммерманс
Ну да. Стригизация - это то, что происходит со ссылками, когда они попадают в скалярный контекст. Как это делает "~~ заставляет скалярный контекст" неправильно?
Дейв Шерохман
3
@ Номад Дервиш: Скалярный контекст / = строковое. Например, "$ n = @a" является скалярным контекстом. "$ s = qq '@ a'" - это строка. Что касается ссылок, «$ ref1 = $ ref2» является скалярным контекстом, но не является строковым.
Майкл Карман
9

tie, переменная привязка интерфейса.

davidnicol
источник
Tie :: File спас мой день один раз!
MHD
9

«Режим отчаяния» конструкций управления циклами 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";

Это то, что я могу придумать, что не было упомянуто.

Schwern
источник
9

Оператор козла *:

$_ = "foo bar";
my $count =()= /[aeiou]/g; #3

или

sub foo {
    return @_;
}

$count =()= foo(qw/a b c d/); #4

Это работает, потому что назначение списка в скалярном контексте дает количество элементов в списке, который назначается.

* Обратите внимание, на самом деле не оператор

Чес. Owens
источник
Это самый (ну, наименьший) красивый «оператор» за всю историю.
Крис Латс