Приховані особливості Perl?


143

Які є справді корисні, але езотеричні особливості мови в Perl, які ви насправді змогли використати для виконання корисної роботи?

Правила:

  • Спробуйте обмежити відповіді ядром Perl, а не CPAN
  • Наведіть приклад та короткий опис

Приховані функції, які також можна знайти в інших прихованих функціях інших мов:

(Це все з відповіді Коріона )

  • С
    • Пристрій Даффа
    • Переносність та стандартність
  • C #
    • Котирування списків та рядків з розділеним пробілом
    • Простіри імен
  • Java
    • Статичні ініталізатори
  • JavaScript
    • Функції - громадяни першого класу
    • Блокування та закриття блоку
    • Методи виклику та доступу до них непрямим шляхом через змінну
  • Рубін
    • Визначення методів за допомогою коду
  • PHP
    • Повсюдна онлайн-документація
    • Магічні методи
    • Символічні посилання
  • Пітон
    • Зміна значень однієї лінії
    • Можливість замінити навіть основні функції власним функціоналом

Інші приховані функції:

Оператори:

Цитуючи конструкції:

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

Модулі, прагми та параметри командного рядка:

Змінні:

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

Регулярні вирази:

Інші особливості:

Інші хитрощі та метавідповіді:


Дивитися також:


Більшість цих особливостей є у повсякденному використанні, деякі трапляються у більшості сценаріїв Perl, а більшість перелічених у розділі "Інші" все ще походять з інших мов.
reinierpost

Відповіді:


54

Оператор відкидання корисний для пропускання першої ітерації під час перегляду записів (зазвичай рядків), повернутих файловою ручкою, без використання змінної прапора:

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

Запустіть perldoc perlopі знайдіть "flip-flop" для отримання додаткової інформації та прикладів.


Насправді це зроблено з Awk, де ви можете робити перевертання між двома візерунками, написавши pattern1, pattern2
Бруно Де Фрейне

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
Я думаю, що вашим прикладом використання букв для розмежування рядків має бути " Просто ще один хакер", а не "Реагуйте ще один хакер на перл" = P
Кріс Лутз

Найгірше - те, що ви можете використовувати інші речі як роздільники. Навіть дужки, що закриваються. Дійсні такі: s} regex} заміна} 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
Ерік Стром

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 || робити {мій $ z; 3 або 4 лінії виведення; $ z};
RET

39

Оператори ++ та unry - працюють не тільки на числах, але й на рядках.

my $_ = "a"
print -$_

відбитки

print ++$_

відбитки b

$_ = 'z'
print ++$_

друкує аа


3
Цитувати perlvar: "Оператор автоматичного зменшення не є магічним". Так --що не працює на рядках.
moritz

"aa" не здається природним елементом після "z". Я б очікував наступного найвищого значення ascii, яке є "{".
Ефір

4
Не запитуйте програміста, що відбувається після "z"; запитайте людину. Ця функція чудово підходить для нумерації елементів у довгому списку.
Баррі Браун

17
Коли я був новим у Perl, я сам реалізував цю функцію з точною поведінкою від a до aa, потім показав її колезі, який посміявся, а я сказав: "Дозвольте мені щось показати". Я трохи плакала, але щось дізналася.
Копас

2
@Ether - Якщо ви цього хочете, використовуйте номери та автоматично конвертуйте їх у ASCII ord(). Або напишіть невеликий клас і перевантажте операторів, щоб зробити це за вас.
Кріс Луц

36

Оскільки Perl має майже всі "езотеричні" частини з інших списків, я скажу вам одне, що Perl не може:

Єдине, що Perl не може зробити - це оголити довільні URL-адреси у вашому коді, оскільки //оператор використовується для регулярних виразів.

На випадок, якщо вам не було очевидно, які функції пропонує Perl, ось вибірковий список можливо не зовсім очевидних записів:

Пристрій Даффа - в 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 порівняно з іншими мовами, але все ще думаю, що для Regexes та посилань це може бути раціоналізовано багато. наприклад, найкращий ґрунтовник для регексів
Джон Фергюсон

9
"Єдине, що Perl не може зробити, - це голі довільні URL-адреси у вашому коді, тому що // оператор використовується для регулярних виразів." - це цілковита дурниця.

Дякуємо за ваше розуміння. Я розглядав деякі способи мати головий URL: // ... URL у коді Perl, не використовуючи фільтр джерела, і не знайшов способу. Можливо, ви можете показати, як це можливо? // використовується для регулярних виразів у версіях Perl розміром до 5.8.x.У 5.10 він перестановлюється на визначене або призначення.
Коріон

8
Чому / де ви хочете оголених URL-адрес у своєму коді? Я не можу придумати приклад.
Castaway

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, але потім виконує його як системну команду, не інтерактивно. Повертає весь текст, сформований із стандартного. (Перенаправлення, якщо воно підтримується в ОС, також виходить) Також робиться із зворотними лапками (символ `).

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 варто прискіпливо присідати.
T

my $moreout = qx{type "$path" 2>&1};... Я не знав, що ти можеш це зробити! [TM]
суха

27

Насправді не приховано, але багато кожного дня програмісти Perl не знають про CPAN . Особливо це стосується людей, які не є штатними програмістами або не програмують на Perl повний робочий день.


27

Оператор "для" може бути використаний так само, як "з" використовується в Pascal:

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

Ви можете застосувати послідовність s /// операцій тощо до тієї ж змінної без повторення імені змінної.

ПРИМІТКА: нерозривний пробіл вгорі (& nbsp;) приховав у ньому Unicode, щоб обійти відмітку. Не копіюйте це вставити :)


І "map" робить такий же трюк, як і ... map {....} $ item; Однією з переваг використання "для" над "картою" було б те, що ви можете використовувати поруч, щоб вирватися.
draegtun

2
Крім того, для того, щоб елемент, який маніпулюється, перерахований перед кодом, що виконує маніпулювання, що призводить до кращої читабельності.
Роберт П

@RobertP: Це цілком правильно. Топікалізатор корисний у дискурсі.
tchrist

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
Цікавим кутовим випадком синтаксису Перла є те, що діє: $ _ qw (перелік речей) {...}
ephemient

1
Ви навіть можете зловживати глобальним синтаксисом для цитування слів, якщо ви не використовуєте спеціальних символів, таких як * ?. Так що ви можете написатиfor (<a list of stuff>) { ... }
moritz

1
@ephemient: майже. Це працює лише з лексичними видами: для мого $ x qw (abc) {...} Наприклад: для $ _ qw (abc) {print} # друкує нічого
dland

навіщо додавати ту додаткову лексику, коли ти можеш насолодитися улюбленим замовчуванням Perl? для (qw / abcd /) {print; }
fengshaun

2
@ephemient, @fengshaun, @moritz, @dland: це "зафіксовано" в blead ; дивіться цю нитку p5p .
tchrist

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: це відповідь Аллана (див. Список ревізій). Краще звернутися до цього користувача. Або, оскільки цей користувач залишив Stack Overflow, можливо, не звертайтеся ні до кого особливо (тому справжній експерт Perl може виправити це пізніше).
Пітер Мортенсен

3
@Hai: Ні, це не некрасиво - насправді це абсолютно протилежне потворному: воно чисто, свіже, мінімально і красиво; словом, це чудово, а мови без нього - ПІТА. @peter mortensen, @toad: Одна відповідь на те, як мати кілька блоків даних в одній програмі, - це використовувати модуль Inline :: Files від CPAN.
tchrist

Inline :: Файли реалізовані за допомогою вихідних фільтрів. Є також дані :: Розділ, який надає декілька вбудованих блоків і не використовує вихідні фільтри.
Пракаш К

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 для певного прийняття рішень:

perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';

Lib::TL просто сканував би як "змінні", так і константи, створив би їх і замінив за потребою.

Знову ж таки, джерельні фільтри можуть бути безладним, але є потужними. Але вони можуть зіпсувати налагодження чогось жахливого - і навіть попередження можуть бути надруковані з неправильними номерами рядків. Я перестав користуватися перемикачем Даміана тому що налагоджувач втратив усі можливості сказати мені, де я насправді. Але я виявив, що ви можете мінімізувати шкоду, змінюючи невеликі розділи коду, зберігаючи їх у тому ж рядку.

Сигнальні гачки

Це досить часто робиться, але це не все так очевидно. Ось вантажник, що підбирає спинку на старому.

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

Двійковий "x" є оператором повторення :

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

Він також працює зі списками:

print for (1, 4, 9) x 3; # print 149149149

Це одна з причин, чому Perl користувався такою популярністю у хакерів. perl -e 'друк 0x000 x 25';
JJ

4
Моє улюблене використання для цього - генерування заповнювачів для останньої частини оператора SQL INSERT: @p = ('?') X $ n; $ p = приєднатися (",", @p); $ sql = "ВСТАВКА ... ЦІННОСТІ ($ p)";
skiphoppy

24

Перевірка тантів. Якщо увімкнено перевірку танти, Perl загине (або попередить, разом із)-t ), якщо ви спробуєте передати загрожуючі дані (грубо кажучи, дані за межами програми) в небезпечну функцію (відкриття файлу, виконання зовнішньої команди тощо). Це дуже корисно при написанні встановлених сценаріїв або 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: Чому це називається?
tchrist

@tchrist - бо це, мовляв, схоже на те, що двоє людей потирають носи. У профілі, якщо ви бачите, що я маю на увазі.
martin clayton

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 comapre-функцій, це єдине повернення значення, яке я знаю цілою мовою 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)
bukzor

18

Це метавідповідь, але поради Perl архіви містять всілякі цікаві хитрощі, які можна виконати за допомогою Perl. Архів попередніх порад є он-лайн для перегляду, і його можна підписати через список розсилки або канал атомів.

Деякі з моїх улюблених порад включають створення виконавчих файлів за допомогою PAR , використання автоматичної автоматичної передачі винятків та використання конструкцій перемикача та смарт-відповідника в 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 вигадав стільки розширень regexp, що інші програми зараз часто використовують pcre (сумісний з perl regex) замість оригінальної мови.
Сек.

Прочитайте маленьке розмиття тут perldoc.perl.org/… :-D
JJ

Перл справді (наскільки я знаю) лідирував на упаковці, коли мова йде про регулярні виразки.
Бред Гілберт

Наскільки я знаю, це все ще експериментально, і може не працювати так само, як у майбутніх Perls. Не кажучи про те, що це не корисно, але трохи безпечніше і так само корисну версію можна знайти у прапорі s /// Command / e: s/(pattern)/reverse($1);/ge;# обертає всіх patterns.
Кріс Лутц

@Chris Lutz, @Leon Timmerman: Зауважте, що ці дві конструкції зараз є спокійними. Також зауважте, що другий більше не потрібно використовувати для здійснення рекурсивних моделей, тепер, коли ми можемо повторюватись для груп захоплення. @Brad Gilbert: Це правильно, хоча PCRE робить гідну роботу з відстеження нас; Однією з областей досконалості регулярних виразів, де Perl є абсолютно беззаперечним, є його доступ до властивостей Unicode; бачити моє unitrio розподілу uninames, unicharsі особливо unipropsбачити тільки частину того , що я маю в виду.
tchrist

13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

\ G якір. Це спекотно .


3
... і вказується позиція кінця попереднього матчу.
Дейв Шерохман

1
Але ви повинні викликати свій регулярний вираз у скалярному контексті.
davidnicol

@davidnicol: наведений вище код працює. Чи можете ви уточнити, що ви маєте на увазі?
JJ

13

The m//Оператор має деякі маловідомі окремі випадки:

  • Якщо ви використовуєте ? як роздільник, він відповідає лише один раз, якщо ви не телефонуєте reset.
  • Якщо ви використовуєте 'як роздільник, візерунок не інтерполюється.
  • Якщо шаблон порожній, він використовує шаблон з останнього успішного збігу.

2
Вони більше схожі на приховані гати, ніж на приховані функції! Я не знаю нікого, хто їх любить. Нитка на p5p деякий час назад обговорювала корисність передбачуваного прапора m / $ foo / r, де / r означало б не інтерполяцію (літера не важлива), оскільки ніхто не може згадати єдину цитату.
dland

2
@dland: Погоджено; Я б назвав ці приховані неправильні функції і ніколи не використовував би їх у виробничому коді.
Майкл Карман

7
Я не уявляю, що програміст Perl не може згадати (або навіть здогадуватися), що окремі котирування не мають інтерполяції. Його використання з цією семантикою є майже універсальною мовою , який я вважав за краще б очікувати , що це буду так ...
Сундар - відновить Моніка

і якщо шаблон порожній і останній успішний збір був складений з модифікатором / o, відтепер він буде застряг на цьому шаблоні.
davidnicol

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 також представляє "оператора розумних відповідностей" ~~, який може робити збіги з регулярними виразами, може виглядати, чи міститься елемент у масиві тощо.
moritz

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

Це не правильно! ~~ не є безпечним у посиланнях! Це їх строфізує.
Леон Тіммерманс

Ну так. Стрифікація - це те, що відбувається з посиланнями, коли їх примушують до скалярного контексту. Як це робить "~~ сили скалярного контексту" неправильним?
Дейв Шерохман

3
@Nomad Dervish: Скалярний контекст / = стрифікація. наприклад, "$ 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. "використовувати 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.