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


143

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

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

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

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

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

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

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

Операторы:

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

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

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

Переменные:

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

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

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

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


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


Большинство из этих функций используются каждый день, некоторые встречаются в большинстве сценариев 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/

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,

Павел


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

Я фанат документации 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 ни на одном другом языке его нет .


Я понятия не имел, что 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 //.


1
Я иногда использую qw "", чтобы подсветка синтаксиса подсветила его правильно.
Брэд Гилберт

У меня работает в SlickEdit. :)
Роберт П

1
@fengshaun, редакторы, которые я обычно использую , выделяют их правильно. Я имел в виду, частично, подсветку синтаксиса в StackOverflow.
Брэд Гилберт

@Brad Gilbert: Переполнение стека не может (ну, не делает) анализ Perl, который стоит приседать. ☹
tchrist

my $moreout = qx{type "$path" 2>&1};... Я не знал, что ты мог сделать это! [TM]
dland

27

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


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.


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


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

Это одна из причин, почему 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. Это может спасти вас от множества опечаток.


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

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, так что я, очевидно, очень высоко ценю их. ;)


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

1
Autodie выглядит очень красиво.
j_random_hacker

18

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


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. Это горячее .


3
... и это указывает на позицию конца предыдущего матча.
Дейв Шерохман

1
Но вы должны называть свое регулярное выражение в скалярном контексте.
Давидникол

@davidnicol: приведенный выше код работает. Можете ли вы уточнить, что вы имеете в виду?
JJ

13

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

  • Если вы используете ?в качестве разделителя, он совпадает только один раз, если вы не позвоните reset.
  • Если вы используете 'в качестве разделителя, шаблон не интерполируется.
  • Если шаблон пуст, он использует шаблон из последнего успешного совпадения.

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
}

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 без необходимости повторяться.


10

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

print ~~ localtime;

такой же как

print scalar localtime;

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

print localtime;

5
Это особенно непонятно, потому что perl5.10.0 также вводит «оператор интеллектуального сопоставления» ~~, который может выполнять сопоставление с регулярным выражением, может проверять, содержится ли элемент в массиве и так далее.
Мориц

Это не неясно, это запутано (и полезно для гольфа и JAPH).
Майкл Карман

Это не правильно! ~~ не безопасно на ссылках! Это приводит их в соответствие.
Леон Тиммерманс

Ну да. Стригизация - это то, что происходит со ссылками, когда они попадают в скалярный контекст. Как это делает "~~ заставляет скалярный контекст" неправильно?
Дейв Шерохман

3
@ Номад Дервиш: Скалярный контекст / = строковое. Например, "$ n = @a" является скалярным контекстом. "$ s = qq '@ a'" - это строка. Что касается ссылок, «$ ref1 = $ ref2» является скалярным контекстом, но не является строковым.
Майкл Карман


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";

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


9

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

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

или

sub foo {
    return @_;
}

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

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

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


Это самый (ну, наименьший) красивый «оператор» за всю историю.
Крис Латс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.