Журнал LinuxFormat - перейти на главную

LXF70:Perl. Сортируем наш код

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
м LXF70:Perl2» переименована в «Perl. Сортируем наш код»)
(Сортировка и перечисление: викификация)
Строка 6: Строка 6:
  
 
=== Сортировка и перечисление ===
 
=== Сортировка и перечисление ===
...
+
Вы помните, как массивы упорядочивают скаляры? Оператор списка Perl действует похожим образом. Это безымянная последовательность скаляров в круглых скобках. Хорошими вариантами использования оператора списка является присвоение значений двум или более переменным в одной инструкции или обмен значениями переменных тем или иным способом.
 +
<source lang="Perl">
 +
($X,$Y,$Z) = ($Y,$Z,$X); # Circular shift
 +
($Name,$Surname,$Phone) = ('John', 'Smith',5556791);
 +
($DARTH_VADER,@JEDI) = ('Anakin Skywalker', 'Yoda', 'Obi-Wan', 'Mace Windu');
 +
</source>
 +
Две первые строчки говорят сами за себя. В третьей строки список из левой части присваивания состоит из скаляра ($DARTH_VaDer) и именованного массива (@JEDI). Все знают, что случится после такого присвоения: на Тёмную Сторону Силы юный Энакин перейдёт в одиночестве. И поскольку вторым элементом списка является массив @JEDI, все остальные рыцари из правой части выражения попадут в него, в том же самом порядке.
 +
 
 +
Давайте теперь посмотрим на функцию splice(), которая используется для удаления, добавления или замены элементов массива. Для начала определим несколько планет:
 +
<source lang="Perl">
 +
@STAR_WARS_PLANETS = ('Naboo', 'Tatooine', 'Geonosis');
 +
</source>
 +
 
 +
Используем splice() для того, чтобы добавить Coruscant и Alderaan сразу после Tatooine:
 +
<source lang="Perl">
 +
splice (@STAR_WARS_PLANETS, 2,0, ('Coruscant', 'Alderaan'));
 +
</source>
 +
 
 +
Первым аргументом этой функции является имя массива, STAR_WARS_PLANETS. Затем идёт индекс элемента (считая с нуля!), с которого мы хотим начать склейку, в нашем случае это Tatooine. Третьим параметром является число элементов для удаления. Сейчас мы не хотим ничего удалять, нам надо только добавить несколько планет, поэтому в качестве третьего параметра передается «0». Последний, необязательный элемент — это список, который будет добавлен в позицию, номер которой вы только что указали. Если этот агрумента не указан, то splice() не добавит в массив ничего.
 +
 
 +
Если вы хотите упорядочить содержимое массива в алфавитном порядке, то вам понадобится функция sort(). По умолчанию она рассматривает содержимое переданного массива как строки, даже если там содержатся числа. Например, если вы введёте в командной строке следующее выражение:
 +
perl -e "@A_LIST = ('Dominions', 180, 3, '10, Downing St.','Admiralty'); \
 +
    print join( \"\n\", sort @A_LIST), \"\n\";"
 +
то получите отсортированный по алфавиту список:
 +
10, Downing St.
 +
180
 +
3
 +
Admiralty
 +
Dominions
 +
Однако функция sort() может руководствоваться и другими критериями:
 +
<source lang="Perl">
 +
@SORTED_LIST = sort AS_I_WANT @UNORDERED_LIST;
 +
</source>
 +
AS_I_WANT — это функция, принимающая два скаляра в качестве аргументов и возвращающая −1, 0 или 1 в зависимости от того, какой параметр оказался меньше согласно вашему критерию. Мы рассмотрим такие функции в последующих выпусках.
 +
 
 +
Последнее замечание про массивы. Есть одна вещь, без которой не может жить ни один Perl-хакер, хотя она вовсе не выглядит как массив.
 +
Я говорю о нашем возлюбленном STDIN, стандартном потоке ввода любой «правильной» Unix-программы. К счастью, им очень просто пользоваться. Я упомянул здесь STDIN потому, что он может быть превращен в массив одним мановением руки:
 +
<source lang="Perl">
 +
@LINES = <STDIN>;
 +
</source>
 +
Вот так, одной единственной инструкцией вы внесли каждую строчку ввода в отдельный элемент массива @LINES. Удобно, не правда ли?
 +
 
 
=== Чистый хэш ===
 
=== Чистый хэш ===
 
...
 
...

Версия 05:39, 13 марта 2008

Часть 2. Напуганы непостижимыми операторами Perl и регулярными выражениями? Еще больше напуганы словом «непостижимые»? Марк Фиоретти (Marco Fioretti) может всё объяснить!

Содержание


Перед тем, как отправиться в путешествие по королевству Perl, вы должны запомнить три типа переменных: скаляр, массив и хэш. Отмеченные символом $ скаляры содержат один кусочек информации, например строку. В нашем втором руководстве мы узнаем, как работать с более сложными величинами, массивами и хэшами, а затем покажем вам настоящую черную магию Perl — регулярные выражения.

Сортировка и перечисление

Вы помните, как массивы упорядочивают скаляры? Оператор списка Perl действует похожим образом. Это безымянная последовательность скаляров в круглых скобках. Хорошими вариантами использования оператора списка является присвоение значений двум или более переменным в одной инструкции или обмен значениями переменных тем или иным способом.

($X,$Y,$Z) = ($Y,$Z,$X); # Circular shift
($Name,$Surname,$Phone) = ('John', 'Smith',5556791);
($DARTH_VADER,@JEDI) = ('Anakin Skywalker', 'Yoda', 'Obi-Wan', 'Mace Windu');

Две первые строчки говорят сами за себя. В третьей строки список из левой части присваивания состоит из скаляра ($DARTH_VaDer) и именованного массива (@JEDI). Все знают, что случится после такого присвоения: на Тёмную Сторону Силы юный Энакин перейдёт в одиночестве. И поскольку вторым элементом списка является массив @JEDI, все остальные рыцари из правой части выражения попадут в него, в том же самом порядке.

Давайте теперь посмотрим на функцию splice(), которая используется для удаления, добавления или замены элементов массива. Для начала определим несколько планет:

@STAR_WARS_PLANETS = ('Naboo', 'Tatooine', 'Geonosis');

Используем splice() для того, чтобы добавить Coruscant и Alderaan сразу после Tatooine:

splice (@STAR_WARS_PLANETS, 2,0, ('Coruscant', 'Alderaan'));

Первым аргументом этой функции является имя массива, STAR_WARS_PLANETS. Затем идёт индекс элемента (считая с нуля!), с которого мы хотим начать склейку, в нашем случае это Tatooine. Третьим параметром является число элементов для удаления. Сейчас мы не хотим ничего удалять, нам надо только добавить несколько планет, поэтому в качестве третьего параметра передается «0». Последний, необязательный элемент — это список, который будет добавлен в позицию, номер которой вы только что указали. Если этот агрумента не указан, то splice() не добавит в массив ничего.

Если вы хотите упорядочить содержимое массива в алфавитном порядке, то вам понадобится функция sort(). По умолчанию она рассматривает содержимое переданного массива как строки, даже если там содержатся числа. Например, если вы введёте в командной строке следующее выражение:

perl -e "@A_LIST = ('Dominions', 180, 3, '10, Downing St.','Admiralty'); \
    print join( \"\n\", sort @A_LIST), \"\n\";"

то получите отсортированный по алфавиту список:

10, Downing St.
180
3
Admiralty
Dominions

Однако функция sort() может руководствоваться и другими критериями:

@SORTED_LIST = sort AS_I_WANT @UNORDERED_LIST;

AS_I_WANT — это функция, принимающая два скаляра в качестве аргументов и возвращающая −1, 0 или 1 в зависимости от того, какой параметр оказался меньше согласно вашему критерию. Мы рассмотрим такие функции в последующих выпусках.

Последнее замечание про массивы. Есть одна вещь, без которой не может жить ни один Perl-хакер, хотя она вовсе не выглядит как массив. Я говорю о нашем возлюбленном STDIN, стандартном потоке ввода любой «правильной» Unix-программы. К счастью, им очень просто пользоваться. Я упомянул здесь STDIN потому, что он может быть превращен в массив одним мановением руки:

@LINES = <STDIN>;

Вот так, одной единственной инструкцией вы внесли каждую строчку ввода в отдельный элемент массива @LINES. Удобно, не правда ли?

Чистый хэш

...

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

...



Подсказка

Подсчёт числа элементов массива
Как можно узнать, сколько элементов содержится в массиве или хэше? Очень просто, присвоить их скалярной переменной! Поскольку она может содержать только одно число, Perl поместит туда число элементов массива. Тот же способ работает с хэшами. Функция keys возвращает массив, содержащий только ключи хэша, так что его размер можно узнать следующим образом:

$HOW_MANY_JEDI = @JEDI;
$HOW_MANY_ITEMS_INTO_AN_HASH = keys %SOME_HASH;

Как разрушить свою жизнь регулярными выражениями

Perl, вероятно, содержит гораздо больше регулярных выражений, чем все другие языки программирования. Для того, чтобы своими глазами увидеть, насколько мощными и неудобными они могут быть, посмотрите на самое длинное из всех, что я видел — http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html. Говорят, что оно проверяет правильность адреса e-mail, но я не могу это проверить. Если хотите научиться создавать такие же, прочитайте книгу Джефри Фридла «Регулярные выражения» (Jeffrey Friedl, «Mastering Regular expressions», O’Reilly, 2002).

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

Здесь приведён список основных метасимволов, используемых в регулярных выражениях Perl. Скопируйте его и держите поближе к клавиатуре, он действительно помогает сэкономить время.

  • . — Любой символ за исключением перевода строки
  • ^ — Начало строки
  • $ — Конец строки
  • * — Ноль или более предыдущих символов
  • + — Один или более предыдущий символ
  •  ? — Ноль или один предыдущий символ
  • \n — Перевод строки
  • \t — Табуляция
  • \w — Числа и алфавитные символы, вне зависимости от регистра
  • \W — Все символы, кроме букв или цифр
  • \d — Старые добрые цифры: 0, 1 и так до 9.
  • \D — Всё, кроме цифр.
  • \s — Пробельные символы: пробел, табуляция, перевод строки.
  • \S — Любой не пробельный символ.
  • \b — Граница слова.
  • | — Выбор из двух вариантов (например A|B).
  • [] — Квадратные скобки определяют диапазон символов.
  • () — Круглые скобки сохраняют соответствующую им подстроку.

Примечания: Когда вам необходимо вставить в регулярное выражение один из этих символов в его буквальном смысле, например знак «+», нужно поставить перед ним обратную косую черту (\).

A+ # Одна или несколько букв A
\+ # один знак "+"
\++ # Один или несколько знаков "+"
Персональные инструменты
купить
подписаться
Яндекс.Метрика