Инструменты для преобразования 8-битных управляющих символов C1 в последовательности ESC?

380
Rehno Lindeque

Стандарт ECMA-48 («escape-последовательности ANSI») описывает два способа кодирования набора управляющих кодов C1: использование двухсимвольных последовательностей ESC или, альтернативно, использование 8-разрядных управляющих символов.

В статьях Википедии объясняется, что двухсимвольные последовательности ESC больше подходят для использования с UTF-8.

Цитирование из escape-кода ANSI :

Стандарт гласит, что в 8-битных средах эти двухбайтовые последовательности могут быть объединены в один управляющий код C1 в диапазоне 0x80–0x9F. Однако на современных устройствах эти коды часто используются для других целей, таких как части UTF-8 или для символов CP-1252, поэтому используется только 2-байтовая последовательность.

и из контрольных кодов C0 и C1 :

Символам C1 в Unicode требуется 2 байта для кодирования в UTF-8 (например, CSI в U + 009B кодируется как байты 0xC2, 0x9B в UTF-8). Таким образом, соответствующие функции управления чаще доступны с использованием эквивалентной двухбайтовой escape-последовательности, предназначенной для использования с системами, которые имеют только 7-битные байты.


Есть ли какие-либо инструменты командной строки, которые можно использовать для прямого преобразования 8-битных управляющих символов C1 (как указано в ECMA-48) в двухсимвольные последовательности ESC?

Моя лучшая попытка на данный момент - попытаться использовать iconv:

$ printf $(echo -en "\x9b") | iconv --from-code=ANSI_X3.4 --to-code=UTF-8 | od -t x1 iconv: illegal input sequence at position 0 

В целях отладки я использую od -t x1для перевода результата обратно в шестнадцатеричное. Результат, который я надеюсь получить, будет таким же, как результат выполнения:

$ printf $(echo -en "\x27[") | od -t x1 0000000 27 5b 0000002 

Другими словами, существует ли инструмент командной строки, в котором вы можете передать в виде управляющего символа C1 \x9bи получить обратную escape-последовательность, как \x27[?

РЕДАКТИРОВАТЬ: Или, как справедливо предлагает egmont, более уместно, интерактивный инструмент, а не то, что вы трубите в.

2
Не могли бы вы дать больше контекста общей проблемы? Откуда поступают данные? Это устаревшее приложение, которое вы не можете изменить? Он обрабатывает не-ASCII символы? Если да, то в какой кодировке? Зачем вам нужно конвертировать из C1 в C0? Это приложение не работает в эмуляторе терминала? Вы действительно ищете инструмент командной строки, который обрабатывает «автономные» данные, или вам нужно преобразование во время выполнения (как, например, сделал бы `luit`, если бы у него была такая опция)? Какую проблему на самом деле вы пытаетесь решить? egmont 6 лет назад 1
@egmont luit выглядит многообещающе. Я сообщу, если это будет работать для моих целей. Я думаю, что в этом случае стоило бы обратиться к ответу. Я работаю над некоторым программным обеспечением для автоматизации терминала, которое использует псевдотерминал для подключения к удаленному компьютеру с устаревшим программным обеспечением (немного сложно разобраться в деталях). В основном ищет ярлык для преобразования набора символов C1 отдельно, чтобы вместо этого придерживаться современных кодов ESC. Rehno Lindeque 6 лет назад 0
Для человека, который проголосовал против: я потратил огромное количество времени на чтение и поиск нужного инструмента в Google. Я также написал раздел, мотивирующий, почему желательно преобразовать символы C1 в последовательности ESC (несовместимость с UTF-8). Пожалуйста, дайте мне знать, если есть что-то, что я могу улучшить, спасибо! Rehno Lindeque 6 лет назад 1
Кстати, мне не нужно конвертировать из C1 в C0. Скорее, это преобразование из 8-разрядного набора символов C1 (одиночные символы) в эквивалентную escape-последовательность из 2 символов, которая изначально предназначалась для 7-разрядных сред, но теперь более распространена из-за того, что 8-разрядный набор символов C1 перекрывается с UTF-8. Я надеюсь, что это поможет немного уточнить. Rehno Lindeque 6 лет назад 0
Ваш последний комментарий: в этом случае все, что вам нужно, - это преобразование кодировки ISO-8859-1 (он же Latin-1) -> UTF-8, возможно, сделанное `luit`. egmont 6 лет назад 0
Обратите внимание, что не все терминальные эмуляторы поддерживают C1 в UTF-8, см., Например, начало http://invisible-island.net/xterm/ctlseqs/ctlseqs.html, почему xterm этого не делает. egmont 6 лет назад 0
Если вам все еще нужно преобразование C1-> C0, я бы, вероятно, посмотрел на исправление `luit`. Любой инструмент командной строки, такой как `iconv` или` sed`, имеет недостаток, заключающийся в том, что они не отображаются как терминалы для приложений, которые генерируют выходные данные (входные данные для этих инструментов); Кроме того, они выполняют буферизацию строк или буферизацию 4 КБ на своем выходе. Вместо этого вам нужно что-то, что ведет себя как терминал, фильтрует поток без буферизации и прозрачно передает другие связанные с терминалом вещи (например, размер окна). Это трудно сделать правильно. Если вы исправите luit, вы можете внести свои изменения в апстрим. egmont 6 лет назад 0
Я начинаю приходить к выводу, что ни `iconv`, ни` luit` не поддерживают символы C1. Вместо того, чтобы быть частью ISO 8859-1, они кажутся [неопределенными в макете кодовой страницы] (https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Code_page_layout). Между тем, страница руководства `luit` гласит:« Выбор альтернативных наборов управляющих символов не поддерживается и никогда не будет ». Rehno Lindeque 6 лет назад 1
С другой стороны [пример ISO 8859-1 в luit] (https://invisible-island.net/luit/luit-figures.html#iso_charsets) гласит: «Обратите внимание, что 0x80-0x9f - это« н / д »( недоступно), поскольку кодировка ISO резервирует их для элементов управления C1. " Rehno Lindeque 6 лет назад 1
Вот как выглядели мои основные попытки для iconv: `printf" \ n \ x9B \ n "| iconv --from-code = ISO8859-1 --to-code = UTF-8 | od -t x1` и для luit: `printf" \ n \ x9B \ n "| luit -c-кодирование ISO-8859-1 | od -t x1`. Rehno Lindeque 6 лет назад 0
Жаль слышать, что "luit" не сработал, как я ожидал. Может быть, патч для обработки этих кодовых точек - это самый простой способ. Только для преобразования вы можете легко создать командную строку `sed`, которая переводит все возможные байты C1 по отдельности, но это будет страдать от проблем буферизации, что не подходит для решения во время выполнения. egmont 6 лет назад 0
Спасибо за помощь в любом случае @egmont, я ценю это. Не волнуйтесь, у меня есть альтернативные идеи, стандартный инструмент был моим первым предпочтением. (Кстати, по поводу проблем с буферизацией, я полагаю, что `sed -u` или` unbuffer -p` могут быть вариантами.) Rehno Lindeque 6 лет назад 1
Дайте нам знать, когда вам удастся придумать что-нибудь. Удачи! egmont 6 лет назад 0

0 ответов на вопрос

Похожие вопросы