Установить выравнивание числовых столбцов при форматировании данных в виде таблицы.

Вопрос или проблема

Я использую column -t для форматирования данных для удобного просмотра в оболочке, но, похоже, нет возможности указать выравнивание столбцов (например, выравнивание по правому краю).

Есть ли однострочные команды Bash, чтобы это сделать? У меня произвольное количество столбцов.

Кажется, что в более новых версиях column имеется опция для выравнивания по правому краю определенных столбцов:

   -R, --table-right columns
          Выравнивание по правому краю текста в указанных столбцах.

Пример:

$ echo -e "a 1 2\nb 12345 678.90" | column -t -R 2,3
a      1       2
b  12345  678.90

С точки зрения простоты, я бы использовал awk

column -t filename | awk '{for (i=0; i<NF; i++){l=index($0, $i)+1;printf "%*s ", index($0, $(i+1))-l, $i}printf "%*s\n", index($0, $NF)-l, $NF}'

Это делает шире немного

ОБНОВЛЕНИЕ: добавлен скрипт (не однострочник), который позволяет выбрать, какие столбцы вы хотите выровнять… Он поддерживает выравнивание влево (по умолчанию) и вправо (не по центру). Из коробки ожидается, что поля разделены табуляцией. Вы можете изменить разделитель колонок через $S.

RJustCol=(2 3 5)  # Установите столбцы для выравнивания по правому краю.
RJustRex=; Q=$'\x01'; R=$'\x02'; S=" | "
for r in ${RJustCol[@]} ;do  # Построить регулярное выражение для выравнивания по правому краю.
  RJustRex="${RJustRex}s/^(([^\t]+\t){$((r-1))})([^\t]+)\t/\1\3$R\t/; "
done
sed -r "s/$/\tZ/g; s/^/$Q/; s/\t/\t$Q/g; $RJustRex" file |
  column -t -s $'\t' | 
    sed -r "s/  $Q/$Q/g; s/$Q([^$Q$R]*)$R([^$Q]*)/$S\2\1/g; s/$Q/$S/g; s/Z$//"

Обычный вывод:

| The Lost Art       |   +1255 |  789 | Los                 |     -55 | 
| of the Idle Moment | -159900 | 0123 | Fabulosos Cadillacs | +321987 | 

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

Option -n
        По умолчанию команда column объединяет несколько соседних
        разделителей в один разделитель при использовании --t опции;
        эта опция отключает это поведение. Эта опция является расширением Debian
        GNU/Linux.

С этого момента представлено оригинальное решение, которое связано с вопросом, но не решает его основную проблему напрямую.

Вот “однострочник”, который подходит для целых чисел (и допускает знаки +/-) .. Карандаш “X” заставляет column дополнять последнюю ячейку справа.

sed 's/$/\tX/g' file |column -t |sed -r 's/([-+]?[0-9.]+)( +)/\2\1/g; s/^  //; s/X$//'

Обычный вывод

  +1255  789  011      -55       34
-159900   33  022  +321987  2323566

Если у вас есть значения с плавающей запятой, или плавающие с целыми числами, или просто целые числа (с необязательными ведущими знаками +/-), требуется немного больше изменений.

sed -r 's/$/\tX/; 
        s/([-+]?[0-9]+\.[0-9]+)\t/\1@\t/g
        s/([-+]?[0-9]+)\t/\1.@\t/g
        s/\./\t./g' file |
  column -t |
    sed -r 's/  \././g
            s/([-+]?[0-9.]+)( +)/\2\1/g
            s/\.@/ /g
            s/@//g
            s/ +X$//'

Обычный вывод

+1255       789   0.11   -55           34
  -15.9900   33   0.22  +321.987  2323566

Ответ или решение

Форматирование числовых столбцов в shell может быть сложной задачей, особенно если требуется выравнивание по правому краю. Если вы используете команду column -t для удобного отображения данных, вам может не хватать возможности настройки выравнивания, например, для числовых столбцов. К счастью, в более новых версиях утилиты column появилась возможность указания выравнивания колонок.

Использование команды column с выравниванием по правому краю

Современные версии column поддерживают флаг -R, с помощью которого можно выравнивать текст в указанных столбцах по правому краю. Пример использования:

echo -e "a 1 2\nb 12345 678.90" | column -t -R 2,3

Результат выполнения:

a      1       2
b  12345  678.90

Использование awk для выравнивания

Если вашей версии column не хватает нужных функций, можно использовать awk для достижения желаемого результата. Следующий скрипт, хотя и является несколько более громоздким, может помочь выстроить столбцы:

column -t filename | awk '{for (i=0; i<NF; i++){l=index($0, $i)+1;printf "%*s ", index($0, $(i+1))-l, $i}printf "%*s\n", index($0, $NF)-l, $NF}'

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

Расширенный скрипт для настраиваемого выравнивания

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

RJustCol=(2 3 5)  # Устанавливаем столбцы для правого выравнивания.
RJustRex=; Q=$'\x01'; R=$'\x02'; S=" | "
for r in ${RJustCol[@]} ;do
  RJustRex="${RJustRex}s/^(([^\t]+\t){$((r-1))})([^\t]+)\t/\1\3$R\t/; "
done
sed -r "s/$/\tZ/g; s/^/$Q/; s/\t/\t$Q/g; $RJustRex" file |
  column -t -s $'\t' | 
    sed -r "s/  $Q/$Q/g; s/$Q([^$Q$R]*)$R([^$Q]*)/$S\2\1/g; s/$Q/$S/g; s/Z$//"

Вывод будет выглядеть следующим образом:

| The Lost Art       |   +1255 |  789 | Los                 |     -55 | 
| of the Idle Moment | -159900 | 0123 | Fabulosos Cadillacs | +321987 | 

Особенности и нюансы команды column

Следует учитывать, что команда column может не работать ожидаемо с пустыми ячейками, что можно уладить с помощью опции -n.

Заключение

Для пользователей новейших версий Linux задача может быть решена с помощью всего лишь одного-двух флагов. В других случаях, выравнивание числовых данных потребует более нестандартных подходов с использованием утилит вроде awk и sed. Это позволит добиться аккуратной табуляции данных в shell, что важно для восприятия и анализа информации.

Оцените материал
Добавить комментарий

Капча загружается...