Мне нужно иметь возможность вставлять двоичные данные в терминал. По какой-то причине каждый байт за пределами диапазона ASCII ( 0x80
- 0xff
) вставляется как одна и та же последовательность из трех байт 0xef 0xbf 0xbd
.
Например:
$ echo -en "\x80" | xclip
$ hd
<paste><EOF>
00000000 ef bf bd |...|
00000004
Это как-то связано с кодировкой символов, используемой терминалом, поскольку если я изменю ее с UTF-8 на ISO 8859 или аналогичную, каждый символ в расширенном диапазоне будет переведен в 0x3f
.
Есть ли у кого-нибудь идеи, как вставить произвольные двоичные данные в терминал?
Редактировать:Похоже, это очень зависит от терминала. Пример выше в Konsole. Я получаю желаемое поведение в xterm, а Gnome Terminal вообще не позволяет вставлять символы в расширенном диапазоне. Любое решение, специфичное для Konsole, все равно будет оценено.
решение1
ef bf bd
это кодировка UTF-8ЗАМЕНА ПЕРСОНАЖА(�), который «используется для замены входящего символа, значение которого неизвестно или непредставимо в Unicode».
То, что вы описываете, не является "расширенным ASCII", а скорее двоичными данными. Некоторые байты в диапазоне 0x80
- 0xff
не являются допустимыми ISO 8859, поэтому понятно, что некоторые программы воспринимают это как неизвестный символ.
Вы можете попробовать использовать 8-битную кодировку символов, которая использует все 255 позиций, например, кодовую страницу IBM 850.
Но тогда программа, из которой вы копируете, может также интерпретировать данные. И что произойдет, если вы вставите нулевой байт или терминальную управляющую последовательность? Весь подход, похоже, обречен на провал.
решение2
Терминалы, как правило, не предназначены для приема двоичного ввода: они ожидают, что управляющие символы будут иметь особое значение в приложениях, и сами выполняют некоторую обработку управляющих символов (в основном в несколько сигналов).
Исключением является term
режим Emacs (или один из его вариантов), который обрабатывает вставленные данные как необработанный текст, передаваемый в приложение.
Обычный метод предоставления двоичного ввода приложению — перенаправление его ввода из файла или канала. Если данные находятся в буфере обмена X, можно использовать xclip
или xsel
:
xclip -o | myapp
xsel -o | myapp
решение3
Ожидаемое поведение сработало здесь с использованиемякуакэтерминал. Я сделал echo -en "\x5" | xclip
и затем средней кнопкой нажал на сеанс экрана с открытым на нем последовательным портом. Устройство отреагировало так же, как и ожидалось.
решение4
Есть несколько комментариев, на которые не было дано подходящего ответа. Вот некоторые моменты:
xterm не принимает "произвольные двоичные данные". Он принимает (в зависимости от локали) UTF-8 или ISO-8859-1. Последний соответствует ICCM, первый является расширением от XFree86. В любой кодировке xterm может интерпретировать эти символы, чтобы (попытаться) предоставить данные из выделения. При вставке текста UTF-8 из выделения в кодировку ISO-8859-1 он будет аппроксимировать наиболее часто используемые символы (включая рисование линий).
Выбор (и вставка) зависят как от источника (где делается выбор), так и от цели (куда вставляется текст). Оба должны согласовать формат данных для выбора/вставки. xterm предоставляет и принимает несколько форматов (см.
button.c
в источниках). Konsole и gnome-terminal используют меньше форматов.Konsole, например, делает выбор X11 как запоздалую мысль. Он использует
QClipboard::Selection
метод. Комментарии к странице Qt в разделеПримечания для пользователей X11Интересное чтение в этом отношении. Нопрочитайте коди посмотрите, что этотолькоподдерживаетCOMPOUND_TEXT
:if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) { // convert COMPOUND_TEXT to a multibyte string XTextProperty textprop; textprop.encoding = *type; textprop.format = *format; textprop.nitems = buffer_offset; textprop.value = (unsigned char *) buffer->data(); char **list_ret = 0; int count; if (XmbTextPropertyToTextList(display, &textprop, &list_ret, &count) == Success && count && list_ret) { offset = buffer_offset = strlen(list_ret[0]); buffer->resize(offset); memcpy(buffer->data(), list_ret[0], offset); } if (list_ret) XFreeStringList(list_ret); }
Аналогично, VTE GNOME используетgtk_clipboard_get_for_display, в целом следуя примеру Qt.
IBM 850 — это 8-битная кодировка (как ISO-8859-1), и не может представлять заменяющий символ UTF-8. Поэтому ваш терминал использует
?
(символ по умолчанию).
Дальнейшее чтение:
Почему я не могу выбрать/вставить в/из других программ?(часто задаваемые вопросы по xterm)
Символ по умолчанию не всегда является вопросительным знаком.