Изучаем Perl

975b8bba

Еще о поледержателяж


Из примеров вы уже поняли, что поледержатель @““ обозначает выровненное по левому краю поле, которое содержит пять символов, а @“““““ — выровненное по левому краю поле, содержащее одиннадцать символов. Как мы и обещали, опишем поледержатели более подробно.

Текстовые поля

Большинство поледержателей начинается со знака @. Символы, стоящие после него, обозначают тип поля, а число этих символов (включая @) соответствует ширине поля.

Если после знака @ стоят левые угловые скобки (““), поле выровнено по левому краю, т.е. в случае, если значение окажется короче, чем отведенное для него поле, оно будет дополняться справа символами пробела. (Если значение слишком длинное, оно автоматически усекается; структура формата всегда сохраняется.)

Если после знака @ стоят правые угловые скобки (””), поле выровнено по правому краю, т.е. в случае, если значение окажется короче, чем отведенное для него поле, оно будет заполняться пробелами слева.

Наконец, если символы, стоящие после знака @, — повторяющаяся несколько раз вертикальная черта (||||), то поле центрировано. Это означает, что если значение слишком короткое, производится дополнение пробелами с обеих сторон, в результате значение будет расположено по центру поля.

Числовые поля

Следующий тип поледержателя — числовое поле с фиксированной десятичной запятой, полезное для больших финансовых отчетов. Это поле также начинается со знака @; за ним следует один или более знаков # с необязательной точкой (она обозначает десятичную запятую). Опять-таки, знак @ считается одним из символов поля. Например:

format MONEY =



Assets: @#W#.*” Liabilities: @#*”##.*# Net: @t”##*.*#

$assets, $liabilities, $assets-$liabilities

Эти три числовых поля предусматривают шесть знаков слева от десятичной запятой и два справа (в расчете на суммы в долларах и центах). Обратите внимание на то, что в формате используется выражение — это абсолютно допустимо и встречается очень часто.

Ничего оригинального в Perl больше нет: вам не удастся установить формат с плавающей запятой для вывода значений денежных сумм, нельзя также заключить отрицательные значения или что-нибудь подобное в квадратные скобки. Для этого придется писать отдельную программу, например:


format MONEY =

Assets: @“““<“ Liabilities: @““““ Net: @““<““

&cool($assets,10), scool($liab,9), Scool($assets-$liab,10)

sub pretty (

my($n,$width) = @_;

$width -— 2; # учтем отрицательные числа

$n ° sprintf("%.2f",$n); # sprintf описывается в одной из следующих глав if ($n < 0) (

return sprintf ("[t$width.2f]", -$n); # отрицательные числа

# заключаются в квадратные скобки ) else {

return sprintf (" %$width.2f ", $n); # положительные числа выделяются

^

пробелами } }

## body of program:

$assets = 32125.12;

$liab = 45212.15;

write (MONEY) ;



Многостроковые поля



Как уже упоминалось выше, при подстановке значения, содержащегося в строке значений. Perl обычно заканчивает обработку строки, встретив в этом значении_символ новой строки. Многостроковые поледержатели позволяют использовать значения, которые представляют собой несколько строк информации. Эти поледержатели обозначаются комбинацией @*, которая ставится в отдельной строке. Как всегда, следующая строка определяет значение, подставляемое в это поле. В данном случае это может быть выражение, которое дает в результате значение, содержащее несколько строк. Подставленное значение будет выглядеть так же, как исходный текст:

четыре строки значения становятся четырьмя строками выходной информации. Например, приведенный ниже фрагмент программы

format STDOUT = Text Before. @*

$long_string Text After.

$long_string = "Fred\nBarney\nBetty\nWilma\n";

write;

позволяет получить такие выходные данные:

Text Before.

Fred

Barney

Betty

Wilma

Text After.



Заполненные поля



Следующий вид поледержателя — заполненное поле. Этот поледержатель позволяет создавать целый текстовый абзац, разбиение на строки которого выполнено по границам слов. Для этого используются несколько элементов формата, которые работают в совокупности. Но давайте рассмотрим их по отдельности.

Во-первых, заполненное поле обозначается путем замены маркера @ в текстовом поледержателе на символ А



(например, /'<“).

Соответствующее значение для заполненного поля (в следующей строке формата) должно быть скалярной переменной*, содержащей текст, а не выражением, которое возвращает скалярное значение. Это объясняется тем, что при заполнении этого поледержателя Perl изменяет значение переменной, а значение выражения изменить очень трудно.

Когда Perl заполняет данный поледержатель, он берет значение этой переменной и "захватывает" из него столько слов (подразумевая разумное определение термина "слово")**, сколько поместится в этом поле. Эти слова фактически "выдираются" из переменной; после заполнения поля значение переменной представляет собой то, что осталось после удаления слов. Почему делается именно так, вы скоро увидите.

* А также отдельным скалярным элементом массива или хеша, например, $а[3] или $h{"fred").

** Разделители слов задаются переменной $:.

Пока что особой разницы между заполненным полем и обычным текстовым полем не видно; мы выводим в поле ровно столько слов, сколько в нем умещается (за исключением того, что мы соблюдаем границу последнего слова, а не просто обрезаем текст по ширине поля). Удобство использования заполненного поля проявляется, когда в одном формате делается несколько ссылок на одну переменную. Взгляните на этот пример:

format PEOPLE =

Name: @<““““““ Comment: "““““““““““^“““^ $name, $comment

$comment $comment $comment

Обратите внимание: переменная $ comment появляется четыре раза. Первая строка (строка с полем имени) выводит имя и первые несколько слов значения этой переменной. В процессе вычисления этой строки $ comment изменяется так, что эти слова исчезают. Вторая строка опять ссылается на ту же переменную ($comment) и поэтому получает из нее следующие несколько слов. Это справедливо и для третьей, и для четвертой строк. По сути дела, мы создали прямоугольник, который будет максимально заполнен словами из переменной $ comment, расположенным в четырех строках.

Что будет, если полный текст занимает меньше четырех строк? Получатся одна-две пустые строки. Это, наверно, нормально, если вы печатаете этикетки и вам нужно, чтобы в каждом элементе было одинаковое количество строк. Если же вы печатаете отчет, наличие множества пустых строк приведет к неоправданному расходу бумаги.



Чтобы решить эту проблему, нужно использовать признак подавления. Строка, содержащая тильду (~), подавляется (не выводится), если при печати она окажется пустой (т.е. будет содержать только пробельные символы). Сама тильда всегда печатается как пробел и может ставиться в любом месте строки, в котором можно было бы поставить пробел. Перепишем последний пример так:

format PEOPLE = Name: @““““““< Comment: ^“““““““““““““x

$name, $comment

$comment $comment $comment

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

Что будет, если комментарий занимает больше четырех строк? Мы могли бы сделать около двадцати копий последних двух строк этого формата, надеясь, что двадцати строк хватит. Это, однако, противоречит идее о том, что Perl помогает лентяям, поэтому специально для них предусмотрено следующее: любая строка, которая содержит две рядом стоящие тильды, автоматически повторяется до тех пор, пока результат не будет полностью пустой строкой. (Эта пустая строка подавляется.) В итоге наше определение формата приобретает такой вид:

format PEOPLE = Name: @<““““““ Comment: ^“““““““““““““^

$name, $comment

$comment

Таким образом, все будет нормально, сколько бы строк ни занимал комментарий — одну, две или двадцать.

Отметим, что данный критерий прекращения повторения строки требует, чтобы в некоторый момент данная строка стала пустой. Это значит, что в этой строке не нужно размещать постоянный текст (кроме символов пробела и тильд), иначе она никогда не станет пустой.


Содержание раздела