Разработчику. Сборник рецептов PHP
Задавайте вопросы

Расширение и сжатие табуляций

Вернуться назад

Задача

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

Решение

Для замены пробелов на табуляцию или табуляции на пробелы следует применять функцию str_replace():

$r = mysql_query("SELECT message FROM messages WHERE id = 1") or die();
$ob = mysql_fetch_object($r);
$tabbed = str_replace(' ',"\t",$ob->message);
$spaced = str_replace("\t",' ',$ob->message);

print "With Tabs: <pre>$tabbed</pre>
print "With Spaces: <pre>$spaced</pre>";

Однако если для преобразования применяется функция str_replace(), то позиции табуляции нарушаются. Если вы хотите ставить табуляцию через каждые восемь символов, то в строке, начинающейся с пятибуквенного слова и табуляции, необходимо заменить табуляцию на три пробела, а не на один. Для замены табуляции на пробелы с учетом позиций табуляции следует применять функцию pc_tab_expand(), показанную в примере:

Пример: pc_tab_expand()

function pc_tab_expand($a) {
    $tab_stop = 8;
while (strstr($a,"\t")) {
      $a = preg_replace('/^([^\t]*)(\t+)/e',
              "'\\1'.str_repeat(' ',strlen('\\2') *
                $tab_stop strlen('\\1') % $tab_stop)",$a);
}
return $a;
}
$spaced = pc_tab_expand($ob->message);

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

Пример: pc_tab_unexpand()

function pc_tab_unexpand($x) {
        $tab_stop = 8;

$lines = explode("\n",$x);
for ($i = 0, $j = count($lines); $i < $j; $i++) {
    $lines[$i] = pc_tab_expand($lines[$i]);
    $e = preg_split("/(.\{$tab_stop})/",$lines[$i],
1,PREG_SPLIT_DELIM_CAPTURE);
        $lastbit = array_pop($e);
        if (!isset($lastbit)) { $lastbit = ''; }
        if ($lastbit == str_repeat(' ',$tab_stop)) { $lastbit = "\t"; }
for ($m = 0, $n = count($e); $m < $n; $m++) {
$e[$m] = preg_replace('/ +$',"\t",$e[$m]);
}
$lines[$i] = join('',$e).$lastbit;
}
$x = join("\n", $lines);
return $x;
}
$tabbed = pc_tab_unexpand($ob->message);

Обе функции принимают в качестве аргумента строку и возвращают ее, модифицировав соответствующим образом.

Обсуждение

Каждая функция предполагает наличие позиций табуляции через каждые восемь пробелов, но это можно изменить, задав переменную $tab_stop. Регулярное выражение в pc_tab_expand() соответствует и группе табуляций, и всему тексту в строке перед группой табуляций. Оно должно соответствовать тексту перед табуляциями, поскольку от длины этого текста зависит количество пробелов, замещающих табуляции, а последующий текст должен быть выровнен по позиции следующей табуляции. Эта функция не просто заменяет каждую табуляцию на восемь пробелов; она выравнивает текст, стоящий после табуляции, по позициям табуляций. Точно так же функция pc_tab_unexpand() не только ищет восемь последовательных пробелов, а затем заменяет их одним символом табуляции. Она делит каждую строку на участки по восемь символов, а затем замещает пробелы в конце этих участков (по крайней мере два пробела) на табуляции. Это не только сохраняет выравнивание текста по позициям табуляций, но и сохраняет пробелы в строке.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ