Почему вывод «столбца» смещен с помощью цветного ввода ANSI?

Я работаю над командной строкой, которая извлекает некоторые данные ( curl ), извлекает соответствующие поля ( awk ) и форматирует их ( столбец ).

Он работает хорошо, хотя он очень уродлив (но весь мой скрипт начинается с «слишком длинного и уродливого» однострочного шрифта), но когда я пытаюсь получить цветную колонку, вы ошибаетесь.

Это простая (уменьшенная) версия, которая работает :

curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null \ | awk 'BEGIN { FS= "|"; OFS= "|" } {print $1, $2, $5, $10, $11, $13}' \ | column -t -s '|' 

Теперь я хочу подчеркнуть некоторые поля, а затем добавить некоторый код escape ANSI в awk:

 curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null \ | awk 'BEGIN { FS= "|" ; OFS= "|" } \ $13~/Rieti/||/Perugia/ {$13="\033[1;31m"$13"\033[0m"} \ $11~/[0-9]+/ && $11 > 5.8 {$11="\033[1;33m"$11"\033[0m"} {print $1, $2, $5, $10, $11, $13 }' \ | column -t -s '|' 

Теперь выравнивание неверно (см. Рисунок).

введите описание изображения здесь

Зачем? И как я могу это исправить?

ОБНОВИТЬ

Я уже видел вопрос « Проблема с командами столбца и цветовыми кодами», но не решает проблему, потому что его ответы применяются и работают в случае полностью цветной линии.

В моем случае я не могу применять или адаптировать ответы (или я не могу), потому что:

  1. Проблема ограничена случаем, когда цвет столбца $ 11 окрашен независимо от последующего столбца.
  2. Я не вижу хороший или элегантный способ добавить цветовой код после столбца.
    Если я отправлю вывод столбца в awk для теста, я не знаю, как проинструктировать awk для правильного разделения полей (если поля были разделены большим пространством, я мог бы использовать регулярное выражение, но в некоторых случаях разделение выполняется на одном пространстве, и awk не знали бы, как распознавать пробелы между словами и пространствами как Сепараторы полей).

Единственное, что я вижу, это то, что если я переместил код сброса с присвоения блоку печати, первая строка была бы лучше отстоящей, например, версия с равным выходом (см. Ниже, \033[0m подчеркнута во второй командной строке): введите описание изображения здесь

Затем, как мы можем это исправить? Есть другой способ, более элегантный, чтобы раскрасить, как я?

(Я знаю, я могу сделать это лучше с некоторыми строками perl, но мне это интересно)

One Solution collect form web for “Почему вывод «столбца» смещен с помощью цветного ввода ANSI?”

Могут быть три простых способа исправить это:

  1. всегда используйте escape-последовательности в этих столбцах, чтобы поддерживать равную длину
  2. поместите эскапады в свои собственные столбцы (4 дополнительных столбца), хотя это добавляет дополнительные пробелы в выходе
  3. формат после column , как вы предложили

Некоторые другие соображения можно найти здесь: Инструмент оболочки для «tablify» входных данных, содержащих escape-коды ANSI .

Для первого варианта вместо использования только \033[1;31m для красного использования \033[31;1m для красного и \033[31;0m для "не красный" или обычный – код 0 отменяет любой предыдущий код, даже тех, кто в той же последовательности. Затем все столбцы имеют одинаковую длину escape-кодов.

 BEGIN { FS=OFS="|" } function colour(ss,cc) { return "\033[" cc ";1m" ss "\033[0m"; } function notcolour(ss,cc) { return "\033[" cc ";0m" ss "\033[0m"; } { if ($13~/(RI|PG)/) { $13=colour($13,31) } else { $13=notcolour($13,31) } if (($11+0) > 5.8) { $11=colour($11,33) } else { $11=notcolour($11,33) } print $1, $2, $5, $10, $11, $13 } 

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

Проблема с этим подходом заключается в том, что это зависит от вашей column и libc . (Мой column от util-linux-2.23.2) не проверяет код возврата из wcswidth() который равен -1, если найдены непечатные данные вместо фактической ширины; это действительно испортит форматирование таблицы. В последней версии от util-linux-2.30.1 используются новые libsmartcols, которые решают эту проблему, но это происходит путем замены непечатаемых версией \x hex-encoded – так что вы полностью теряете исходные экраны: / Что вы можете исправить с неэлегантным:

 curl ... | awk ... | column -t -s '|' | while read -r line; do printf "$line\n"; done 

где printf интерпретирует printf последовательности. Вы можете заменить \033 на \\x1b в своем собственном коде для того же эффекта. Я не уверен, что вы используете Linux.)

Для третьего варианта вам понадобится column который поддерживает -o для установки разделителя вывода, по умолчанию это два пробела. Установите его на « | », затем вы можете использовать это:

 curl ... | column -t -s "|" -o "|" | awk ' BEGIN { FS="|" } function colour(ss,cc) { return sprintf("\033[%i;1m%s\033[0m",cc,ss) } { if ($13~/(RI|PG)/) { $13=colour($13,31) } if (($11+0) > 5.8) { $11=colour($11,33) } print $1, $2, $5, $10, $11, $13 }' 

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

 curl ... | sed -e 's/|/^|/g' | column -t -s^ | awk ... 

Это удваивает разделитель до « ^| », column использует ^ и awk использует | , Это делает предположение, что ^ не входит в данные, конечно. Вместо этого может работать жесткая вкладка.

Я думаю, что теперь вы знаете «почему», но чтобы быть ясным:

  • column может наименовать октеты (или символы) наивно с помощью strlen() / wcslen() , это не будет соответствовать длине, отображаемой терминалом
  • column может рассчитывать длину, используя isprint() , также неверную с выводами терминала
  • column может отказаться (как и мой) в любом столбце, когда встречаются непечатные

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

  • Как напечатать соответствующее значение разделителя полей с рисунком в AWK
  • Условие Awk вместе с заголовком
  • Почему печать работает с awk, но с эхом нет?
  • Как добавить числовой порядок имен файлов Zsh / AWK / ...?
  • суммы столбцов на основе совпадающих полей
  • извлекать строки из большого файла с разделителями табуляции, используя список
  • Regex go Wrong
  • Как вызвать jq внутри awk?
  • Манипулировать некоторые данные с ограниченным разделением в полезный CSV
  • Формат вывода Mysql в сценарии Bash
  • shell: разделение столбцов с помощью awk-стопов, если найдено не целое число
  • Сравните значения записей друг с другом.
  • Interesting Posts

    initrd, построенный с помощью NFS-модуля, не может монтировать NFS-корневой

    Какой пользователь (www-data или vagrant) запускает приложение Laravel в виртуальном сервере Homestead?

    проанализировать файл журнала, который принимает аргумент (время выполнения тестов)

    Как закодировать строку значений с помощью ',' и напечатать ее как список

    Как называется графический трюк этого терминального окна, который показывает акцентированные грани вокруг выделенного текста?

    разделять файл, передавать каждую часть в качестве параметра скрипту, запускать каждый скрипт параллельно

    команда процесса и использование знака процента

    Пакет python3-pyds9 отсутствует в Jessie

    Решение балансировки нагрузки с помощью linux

    Резервное копирование системы в Fedora 14

    Установка RPMS на Centos

    Разве bash делает терминал переводит новую строку (\ n) на возврат каретки (\ r)?

    Как эмулировать эффект KWin по командной строке?

    Почему SSH требует много времени для подключения

    mongodb "захват" порт

    Linux и Unix - лучшая ОС в мире.