AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 414159
Accepted
forumulator
forumulator
Asked: 2018-01-02 09:43:51 +0800 CST2018-01-02 09:43:51 +0800 CST 2018-01-02 09:43:51 +0800 CST

Comportamento do backspace no terminal

  • 772

Trata-se do comportamento do \bcaractere backspace ( ). Tenho o seguinte programa em C:

int main() {
    printf("Hello\b\b");
    sleep(5);
    printf("h\n");
    return 0;
}

A saída no meu terminal é

Helho

com o cursor avançando para a primeira posição da linha seguinte.

Primeiro, a coisa toda é impressa somente após o sono de 5 segundos, então deduzi que a saída do kernel para o terminal é armazenada em buffer de linha. Então agora minhas perguntas são:

  1. Como o \b\bvolta dois espaços, para a posição do (segundo) l, então semelhante a como lfoi substituído por h, o odeveria ter sido substituído por \n. Por que não foi?
  2. Se eu retirar a linha printf("h\n");, ele imprime Helloe volta dois caracteres, sem apagar. Isso que obtive de outras respostas é por causa de um backspace não destrutivo. Por que esse comportamento é diferente para entrada e saída? Ou seja, se eu inserir algo no terminal (mesmo o mesmo programa) e pressionar Backspace, ele apaga o último caractere, mas não a saída. Por quê?

Estou em um sistema Ubuntu no terminal xterm usando o bash, se isso ajudar.

terminal tty
  • 3 3 respostas
  • 7199 Views

3 respostas

  • Voted
  1. Best Answer
    ilkkachu
    2018-01-02T10:59:11+08:002018-01-02T10:59:11+08:00

    Primeiro, a coisa toda é impressa somente após o sono de 5 segundos, de modo que deduzi que a saída do kernel para o terminal é armazenada em buffer de linha.

    Não, a saída do seu programa para o kernel é armazenada em buffer de linha. Esse é o comportamento padrão para stdioquando stdouté um terminal. Adicione a chamada setbuf(stdout, NULL)para desativar o buffer de saída para arquivos stdout. Veja setbuf(3).

    1. Como o \b\bretrocede dois espaços, para a posição de lentão semelhante a como lfoi substituído por h, o odeveria ter sido substituído por \n. Por que não foi?

    Como o caractere de nova linha apenas move o cursor (e rola a tela), ele não é impresso como um caractere visível que ocuparia o lugar de um glifo no terminal. Se assumirmos que tomaria o lugar de um glifo, como seria?

    1. se eu inserir algo no mesmo programa e pressionar Backspace, ele apaga o último caractere, mas não a saída. Por quê?

    Bem, o que acontece quando você digita depende do modo em que o terminal está. Grosso modo, pode ser no modo "cozido" usual, onde o próprio terminal fornece edição de linha elementar (lida com backspaces); ou em um modo "bruto", onde todos os pressionamentos de tecla vão para o aplicativo e cabe ao aplicativo decidir o que fazer com eles e o que gerar em resposta. O modo cozido geralmente acompanha o "eco local", onde o terminal (local para o usuário) imprime os caracteres à medida que são digitados. No modo raw, o aplicativo geralmente se encarrega de ecoar os caracteres digitados, para ter controle total sobre o que está visível.

    Veja, por exemplo, esta questão para discussão sobre os modos de terminal: Qual é a diferença entre um driver de dispositivo “bruto” e um “cozido”?

    Se você executar, por exemplo cat, o terminal estará no modo cozido (o padrão) e lidará com a edição da linha. Bater, por exemplo xBackspaceCtrl-D, resultará catapenas na leitura da entrada vazia, sinalizando o fim da entrada. Você pode verificar isso com strace. Mas se você executar um shell Bash interativo, ele manipulará o backspace por si só e exibirá o que considerar apropriado para fazer o que o usuário espera, ou seja, limpar um caractere.


    Aqui está parte da saída para strace -etrace=read,write -obash.trace bash, após inserir a sequência mencionada xBackspaceCtrl-D:

    read(0, "x", 1)                         = 1
    write(2, "x", 1)                        = 1
    read(0, "\177", 1)                      = 1
    write(2, "\10\33[K", 4)                 = 4
    read(0, "\4", 1)                        = 1
    

    Primeiro, Bash reads e writes the x, enviando-o para o terminal. Em seguida, ele lê o backspace (código de caractere 0177 em octal ou 127 em decimal) e emite o caractere de backspace (octal 010, decimal 8 (*) ) que move o cursor para trás e gera a sequência de controle para limpar o final da linha, <ESC>[K. O último \4é o Ctrl-D, que é usado pelo Bash para sair do programa.

    (* na entrada, Ctrl-Hteria o código de caractere decimal 8. Backspace é o mesmo ou 127 aqui, dependendo novamente de como o terminal está configurado.)

    Em comparação, o mesmo experimento catmostra apenas uma única leitura de zero bytes, a condição de "fim do arquivo". O fim do arquivo pode significar um canal ou soquete conectado sendo fechado, um final real do arquivo ou Ctrl-Drecebido de um terminal no modo cozido:

    read(0, "", 131072)                     = 0
    

    Em particular, catnão vê o x, nem o backspace, nem o código real para Ctrl-D: eles são manipulados pelo terminal. Que pode ser o driver de terminal virtual no kernel; um terminal físico real em uma conexão serial ou algo semelhante; ou um emulador de terminal como xterm rodando na mesma máquina ou na extremidade remota de uma conexão SSH. Não importa para o software userspace.

    • 8
  2. bu5hman
    2018-01-02T10:14:32+08:002018-01-02T10:14:32+08:00

    Os códigos ( \b, \netc) movem o cursor, não o texto.

    Acho que você descobrirá que o comportamento vem dos 'bons velhos tempos', quando tínhamos que manipular o cursor em uma impressora para obter efeitos impressionantes, como fontes em negrito e tachado em teletipo, impressoras de bolas de golfe e similares.

    \bapenas move o ponto de inserção para trás e permite sobrescrever. Em uma tela digital, isso exclui o conteúdo anterior, mas em uma impressora antiga, você obteria o caractere sobreposto.

    \nmove o cursor para uma nova linha, mas deixa o texto na linha antiga para trás. Isso teria sido um CRLF que coloca o cursor de volta no início da linha e informa à impressora para rolar uma linha para cima.

    Os códigos CR, LF e CRLF estão novamente ligados à necessidade de manipular dispositivos antigos para obter esses efeitos modernos.

    ..... e não havia como excluir caracteres de uma página impressa. Esperava-se que você acertasse antes de postar para imprimir.

    EDITAR

    Re ponto 2. Entrada e saída fazem coisas diferentes porque você está mandando.

    \bé equivalente à seta para a esquerda com INSERT desligado, não delete.

    \né equivalente à seta para baixo (LF) e HOME (CR), não à tecla 'enter'.

    • 4
  3. G-Man Says 'Reinstate Monica'
    2018-01-02T22:40:11+08:002018-01-02T22:40:11+08:00

    Em primeiro lugar, se você quiser aprender sobre essas coisas, você deve ler

    • Qual é a diferença exata entre um 'terminal', um 'shell', um 'tty' e um 'console'?
    • O TTY desmistificado

    Você pergunta,

    … se eu inserir algo … e pressionar Backspace, ele apaga o último caractere, mas não para a saída. Por quê?

    Aqui estão algumas curiosidades para você: Nos primeiros dias do Unix (década de 1970, antes mesmo de o Linux existir), o backspace 1 não apagava os caracteres de entrada e os usuários odiavam. Você digitaria beast, pressionaria Backspace três vezes e ainda teria um olhar maligno be|astolhando para você ( |representa o cursor). Mesmo depois de digitar st(porque você quis dizer besto tempo todo), a tela ainda dizia best|t, e era confuso.

    Muitos usuários adotaram o hábito de digitar Backspace Space Backspace uma vez para cada caractere que desejavam apagar, a fim de usar os espaços para substituir/destruir os caracteres ruins; ou seja, para apagá -los manualmente . Eventualmente (1979 ou início dos anos 1980), os desenvolvedores cederam e tornaram isso automático:

    Quando você pressiona backspace, a disciplina de linha tty do kernel apaga seu caractere anterior imprimindo (no caso simples) Ctrl-H, um espaço e, em seguida, outro Ctrl-H.
    Fonte: Como o Unix apaga as coisas quando você digita um backspace enquanto digita o texto

    onde “Ctrl-H” é o código de controle para um backspace.

    Em algumas situações, você pode desativar essa opção e obter o comportamento antigo digitando stty -echoe ( echoe = “apagar eco” e -significa “não faça isso”).
    ____
    1 Na verdade, bem no início, backspace não era Backspace — mas isso é outra história.

    • 4

relate perguntas

  • Erro de sintaxe: número fd inválido?

  • traceroute, imprima apenas as informações do gateway

  • Como posso dar uma olhada no ssh?

  • Área de memória Flash Nand de backup

  • Por que o utilitário ssh é considerado um pty?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve