БлогNot. PHP: выравниваем текст по столбцам

PHP: выравниваем текст по столбцам

Речь не идёт о задаче красивого форматирования программного кода отступами (code alignment). Её можно попытаться решить многочисленными плагинами для Notepad++, такими как Ident By Fold или мощный TextFX с собственным меню (правда, все они обычно не работают так, как тебе нужно).

Отметим также, что код на C++ можно подровнять в редакторе среды Visual Studio. Пройдите в верхнее меню Сервис, Параметры, откройте список Текстовый редактор - C/C++ - Табуляция и настройте отступы по блоку так, как вам удобно

Мы хотим более скромно решить задачу columns alignment, то есть, "раскидать" некие строки текста с разделителями (в формате CSV или подобном) по столбцам, ширина каждого из которых определяется максимальной шириной попадающего туда элемента. Например, если разделитель - это пробел, а данные - это

Привет, мир
2 столбца!

то получится один из трёх вариантов результата

Привет,|мир     
2      |столбца!

Привет,|     мир
      2|столбца!

Привет,|  мир   
   2   |столбца!

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

В PHP эта задача, в общем, уже решена стандартной функцией str_pad, нам остаётся лишь обернуть её в небольшой класс ColumnAlinger и снабдить его несколькими настройками:

  • публичное свойство $columns_dividor - символ или строка, разделяющие столбцы в исходном тексте, по умолчанию - табуляция;
  • публичное свойство $output_dividor - символ или строка для разделения столбцов в строке-результате, по умолчанию - пробел;
  • публичное свойство $skip_empty_dividors определяет, пропускать ли пустые строки и столбцы в исходных данных, по умолчанию нет (false);
  • публичный метод set_align позволяет установить выравнивание внутри столбцов, значения приватного свойства $align_type, которые он может установить - те же, что у функции str_pad (STR_PAD_RIGHT - дополнять пробелами справа, STR_PAD_LEFT - слева, STR_PAD_BOTH - с обеих сторон, то есть, центрировать);
  • публичный метод get получает строку с исходным текстом, выполняет всю работу и возвращает строку-результат.

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

<?php
class ColumnAlinger {
 public $columns_dividor, $output_dividor, $skip_empty_dividors;
 private $align_type;

 function __construct ($columns_dividor = "\t", $output_dividor = ' ') {
  $this->columns_dividor = $columns_dividor;
  $this->output_dividor = $output_dividor;
  $this->align_type = STR_PAD_RIGHT;
  $this->skip_empty_dividors = false;
 }

 public function set_align ($align_type) {
  if (in_array($align_type,array(STR_PAD_RIGHT,STR_PAD_LEFT,STR_PAD_BOTH))) $this->align_type = $align_type;
  else $this->align_type = STR_PAD_RIGHT;
 }

 public function get ($data) {
  $fieldsbyrow = array();
  $lines = explode("\n", $data);
  foreach ($lines as $line) {
   if ($this->skip_empty_dividors) {
    $line = trim($line);
    if (empty($line)) continue;
    $line = preg_replace ("/(\s)(\s+)/","$1",$line);
   }
   $fieldsbyrow[] = explode ($this->columns_dividor, rtrim($line));
  }
  $maxfields = max(array_map('count', $fieldsbyrow));
  foreach (range(0, $maxfields-1) as $col) {
   $maxwidth = 0;
   foreach ($fieldsbyrow as $fields)
     $maxwidth = max($maxwidth, strlen($fields[$col]));
   foreach ($fieldsbyrow as &$fields)
     $fields[$col] = str_pad ($fields[$col], $maxwidth, ' ', $this->align_type);
   unset($fields); //очень классический баг PHP, см. http://bugs.php.net/29992
  }
  $result = '';
  foreach ($fieldsbyrow as $fields)
    $result .= implode ($this->output_dividor, $fields)."\n";
  return $result;
 }
}

//Ниже - пример использования класса
 
$text1 = 'Текст со словами, разделёнными
Одним пробелом на столбцы,
А если их мы сможем выровнять,                                     	
То мы, конечно, молодцы!';
$aligner = new ColumnAlinger (' ','|');
echo '<pre>'.$aligner->get($text1).'</pre><hr>';
 
$aligner->set_align (STR_PAD_BOTH);
echo '<pre>'.$aligner->get($text1).'</pre><hr>';  

$aligner->columns_dividor = "\t";
$aligner->output_dividor = ' ';
$aligner->set_align (STR_PAD_LEFT);
$text2= "Заменим\tтабуляции\tпробелами
и\tвыровняем\tтекст\tпо
правым\tграницам\tстолбцов.";
echo '<pre>'.$aligner->get($text2).'</pre><hr>';  

$text3 = '  Теперь  разделители   лишние  есть,

  Мы   это  флажком   захотели  учесть.';
$aligner->columns_dividor = " ";
$aligner->output_dividor = '|';
$aligner->skip_empty_dividors = true;
echo '<pre>'.$aligner->get($text3).'</pre>';
?>
вывод этого скрипта (скриншот)
вывод этого скрипта (скриншот)

19.02.2017, 15:36 [4974 просмотра]


теги: textprocessing программирование php форматы

К этой статье пока нет комментариев, Ваш будет первым