Por que na saída do script (1) a nova linha é CR + LF (estilo dos)?

1

No texto datilografado do comando script (ou seja, no arquivo salvo), a nova linha é CR + LF (\ r \ n), embora a original (alimentada para script ) seja LF. Por quê? Parece que é um problema, que eu não conheço. Alguém pode explicar isso sem muitos detalhes?

Eu não estou em apuros; Eu só estou curioso. :) (Mas eu acho que é melhor consertar isso, ou no leasd deve ser documentado.)

Meu script é do util-linux, mas provavelmente não importa muito.

    
por teika kazura 08.02.2017 / 01:28

3 respostas

0

Minha própria resposta, depois de aprender com a resposta e o comentário de icarus :
Você tem que distinguir "uma nova linha em um arquivo" e "uma nova linha em um console". Em um console, a verdadeira nova linha é, contra-intuitivamente, CRLF, como veremos abaixo.

Na convenção do UNIX, em arquivos de texto, LF significa uma nova linha, e vice-versa, você quer dizer uma nova linha de LF. (Por "você quer dizer", quero dizer dizer em um texto em linguagem natural.) Em DOS CR + LF, e assim por diante. Está bem. Todo mundo sabe disso.

O console

(Unix) é mais complicado. Primeiro você tem que lembrar que LF e CR são códigos de controle, isto é, podem ser usados para controlar um console, por exemplo. ficando em negrito, cor, etc.

Se você alimentar um LF (\ n, alimentação de linha) em um console, obterá uma nova linha. O problema é que, bem, as duas duas capturas são: (1) os consoles são em camadas duplas, por assim dizer; eles consistem em um filtro e uma parte de renderização. (Nomenclatura ad hoc.) O filtro oculto (para usuários comuns) traduz LF para CRLF. (2) O renderizador precisa de CRLF (\ r \ n) para uma nova linha no sentido comum. Veja abaixo para mais.

O arquivo typescript criado pelo comando script (1) registra os caracteres após a entrada para o console é filtrada. É por isso que as novas linhas no typescript são CRLF.

Detalhes & misc. fatos:

  • O renderizador de console imprime LF como "mover o cursor para baixo uma linha" e CR como "move o cursor para o início da linha".
  • Você pode desativar a conversão LF- > CRLF por $ stty -opost e apagá-la por $ stty opost . "opost" é uma abreviação de "Output POSTprocessing".
    • Mais precisamente, opost faz LF- > LFCR quando onlcr é definido. Quando onocr é definido, o CR será excluído quando no início da linha, etc. Ref: POSIX cap 11 " Interface geral do terminal ".
  • A tecla "Enter" é ligada ao LF no Unix, chamado "Return" na terminologia do mapa de teclado. (Veja esta questão para mais detalhes.)
  • Também há variantes de código de escape; man 4 console_codes explica que "ESC D" (\ eD) é alimentação de linha e "ESC E" (\ eE) é nova linha. Se você imprimi-los, "ESC D" é um "movimento cursor para baixo", e "ESC E" um CR + LF, independentemente de ± opost-ness.

Para fazer algumas experiências, recomendo escrever em um console separado. Por exemplo, $ echo -ne '1st\n2nd\r\n3rd\n" > /dev/tty1 grava no primeiro console não-X e /dev/pts/0 é o primeiro terminal X. Esta não é a maneira mais conveniente, mas menos ambígua.

    
por 16.02.2017 / 02:59
4

A razão profunda para a discrepância entre a saída do programa e um fluxo tty capturado (por exemplo, typescript ) é que tty costumava ser impressoras .

Antes do unix, o texto sempre tinha um CRLF no final de uma linha, não porque era considerado a representação lógica de uma terminação de linha, mas porque os caracteres tinham significado físico real: mova a cabeça de impressão até o fim para a esquerda e avance o papel.

O Unix adotou uma abordagem radical: trata os arquivos de texto no disco como um objeto útil por si só (não apenas instruções para uma impressora) e linhas como entidades lógicas. O terminador de linha de dois caracteres é desnecessariamente complicado na visão de mundo unix.

Mas eles tiveram que trabalhar com hardware existente - impressoras e terminais burros CRT que não reconhecem um único caractere de "fim de linha", mas apenas um CR para fazer metade do trabalho e um LF para fazer a outra metade. Então, uma tradução teve que ser feita, e foi feita no local mais próximo possível daquele hardware - no driver do tty.

Desde então, tudo foi compatível com versões anteriores. Então você tem um emulador de terminal que insiste em CRLF e um driver que o fornece quando um programa gera uma nova linha.

    
por 08.02.2017 / 02:13
2

A saída typescript captura todos os caracteres enviados para o arquivo. Se você usar, por exemplo, stty -opost para impedir que o driver do terminal faça sua alteração normal do caractere de nova linha para CR + LF, verá que você tem apenas caracteres LF na saída.

Espero que seja uma dica útil, use

col -b < typescript

para fazer o primeiro passo na limpeza do arquivo.

    
por 08.02.2017 / 01:36