Расширение и сжатие символов табуляции

Проблема

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

Решение

Примените подстановку весьма странного вида:
while ($string =~ s/\t+/' ' x (length($&) * 8 - length(S') % 8)/e)  {
  # Выполнять пустой цикл до тех пор.
  # пока выполняется условие подстановки
}
Также можно воспользоваться стандартным модулем Text::Tabs:
use Text::Tabs;
@expanded_lines  = expand(@lines_with_tabs);
@tabulated_lines = unexpand(@lines_without_tabs);

Комментарий

Если позиции табуляции следуют через каждые N символов (где N обычно равно 8), их несложно преобразовать в пробелы. В стандартном, «книжном» методе не используется модуль Text::Tabs, однако разобраться в нем непросто. Кроме того, в нем используется переменная $', одно упоминание которой замедляет поиск по шаблону в программе.
while (<>)  {
1 while s/\t+/' ' х (length($&) * 8 - length($') %8)/e;
  print;
}
Вы смотрите на второй цикл while и не можете понять, почему его нельзя было включить в конструкцию s///g ? Потому что вам приходится каждый раз заново пересчитывать длину от начала строки (хранящуюся в $'), а не от последнего совпадения. Загадочная конструкция 1 while CONDITION эквивалентна while (CONDITION) {}, но более компактна. Она появилась в те дни, когда первая конструкция работала в Perl несравнимо быстрее второй. Хотя сейчас второй вариант почти не уступает по скорости, первый стал удобным и привычным.
Стандартный модуль Text::Tabs содержит функции преобразований в обоих направлениях, экспортирует переменную $tabstop, которая определяет число пробелок на символ табуляции. Кроме того, это не приводит к снижению быстродействия, потому что вместо $& и $' используются $1 и $2:
use Text::Tabs;
$tabstop = 4;
while (<>) { print expand($_) }
Модуль Text::Tabs также может применяться для «сжатия» табуляции. В следующем примере используется стандартное значение $tabstop, равное 8:
use Text::Tabs;
while (<>) { print unexpand($_) }

См. также

Описание оператора s///



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: