Preciso poder colar dados binários em um terminal. Por alguma razão, cada byte fora do intervalo ASCII ( 0x80
- 0xff
) é colado como a mesma sequência de três bytes 0xef 0xbf 0xbd
.
Por exemplo:
$ echo -en "\x80" | xclip
$ hd
<paste><EOF>
00000000 ef bf bd |...|
00000004
Tem algo a ver com a codificação de caracteres usada pelo terminal, pois se eu mudar de UTF-8 para ISO 8859 ou similar, todos os caracteres no intervalo estendido serão traduzidos para 0x3f
.
Alguém tem uma ideia de como colar dados binários arbitrários no terminal?
Editar:Isso parece ser muito dependente do terminal. O exemplo acima está no Konsole. Obtenho o comportamento desejado no xterm e o Terminal Gnome não permite colar caracteres no intervalo estendido. Qualquer solução específica do Konsole ainda seria apreciada.
Responder1
ef bf bd
é a codificação UTF-8 deCARÁTER DE SUBSTITUIÇÃO(�), que é “usado para substituir um caractere de entrada cujo valor é desconhecido ou não representável em Unicode”.
O que você descreve não é "ASCII estendido", mas sim dados binários. Alguns bytes no intervalo 0x80
- 0xff
não são válidos para ISO 8859, então é compreensível que alguns programas tratem isso como um caractere desconhecido.
Você pode tentar usar uma codificação de caracteres de 8 bits que use todas as 255 posições, como a página de código 850 da IBM.
Mas o programa do qual você está copiando também pode estar interpretando os dados. E o que acontece quando você cola um byte nulo ou uma sequência de escape de terminal? Toda a abordagem parece destinada ao fracasso.
Responder2
Os terminais geralmente não são projetados para aceitar entrada binária: eles esperam que os caracteres de controle tenham um significado especial nas aplicações e fazem eles próprios algum processamento dos caracteres de controle (principalmente em alguns sinais).
Uma exceção é o modo do Emacs term
(ou uma de suas variantes), que trata os dados colados como texto bruto que é passado para o aplicativo.
O método normal de fornecer entrada binária para um aplicativo seria redirecionar sua entrada de um arquivo ou canal. Se os dados estiverem na área de transferência do X, você pode usar xclip
ou xsel
:
xclip -o | myapp
xsel -o | myapp
Responder3
O comportamento esperado funcionou aqui usandoyakuaketerminal. Eu fiz echo -en "\x5" | xclip
e cliquei no botão do meio em uma sessão de tela com uma porta serial aberta. O dispositivo ecoou exatamente como esperado.
Responder4
Existem vários comentários que não obtiveram uma resposta adequada. Aqui estão alguns pontos:
xterm não aceita "dados binários arbitrários". Aceita (dependendo da localidade) UTF-8 ou ISO-8859-1. Este último segue o ICCM, o primeiro é uma extensão do XFree86. Em qualquer codificação, o xterm pode interpretar esses caracteres para (tentar) fornecer os dados da seleção. Se colar texto UTF-8 de uma seleção na codificação ISO-8859-1, ele aproximará os caracteres mais comumente usados (incluindo desenho de linha).
a seleção (e a colagem) dependem da origem (onde a seleção é feita) e do destino (onde o texto é colado). Ambos devem concordar com o formato dos dados para selecionar/colar. xterm fornece e aceita vários formatos (veja
button.c
em fontes). Konsole e gnome-terminal usam menos formatos.O Konsole, por exemplo, faz a seleção do X11 posteriormente. Ele usa o
QClipboard::Selection
método. Comentários da página do Qt na seçãoNotas para usuários do X11é uma leitura interessante a esse respeito. Masleia o códigoe veja que issoapenasapoiaCOMPOUND_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); }
Da mesma forma, o VTE do GNOME usagtk_clipboard_get_for_display, geralmente seguindo o exemplo do Qt.
IBM 850 é uma codificação de 8 bits (como ISO-8859-1) e não pode representar o caractere de substituição UTF-8. Então seu terminal usa
?
(ocaractere padrão).
Leitura adicional: