Qual é a justificativa para \ re \ \ significando coisas diferentes no comando s?

13

Todos sabemos que, ao pesquisar, \né nova linha e \rretorno de carro ( ^M), mas ao substituir \ré nova linha, enquanto \né um byte nulo ( ^@).

Qual a origem dessa assimetria? Dado que esse comportamento é ... peculiar para dizer o mínimo (e bastante contraproducente quando você erra da primeira vez), espero que exista alguma razão histórica bizarra.

(aliás, existe alguma maneira de "consertar" esse comportamento e obter algo mais intuitivo?)

Matteo Italia
fonte

Respostas:

10

No nível mais básico, já existe uma assimetria entre as partes de pesquisa e substituição, :substituteporque a primeira é uma expressão regular e a segunda é o texto, com seqüências de escape adicionais específicas . Isso é destacado apenas pela intuição que você tem sobre o que \nsignifica.

Por exemplo, considere que \nna pesquisa não corresponde a um literal \n. Ele corresponde ao fim da sequência de bytes linha (EOL), que pode ser \r, \r\nou apenas \nem função da 'fileformat'do tampão.

Quanto ao porquê \rde "inserir uma EOL", há um histórico por trás disso. Vi não tinha como lidar com um byte NUL em um arquivo. O Vim melhorou isso, substituindo NUL bytes por um byte NL internamente (desde que as strings C sejam delimitadas por NUL).

Esse detalhe de implementação vazou no comportamento de, :substituteuma vez que \nna substituição é simplesmente inserido na representação interna dessa linha, que é usada para indicar um byte NUL. \rinsere uma EOL, quebrando a linha interna em duas. O Vim, na verdade, não armazena os bytes EOL na memória, em vez de (de) serializá-los ao ler / gravar o buffer.

Agora não pode ser alterado sem quebrar os muitos scripts e a memória muscular de muitos usuários. Felizmente, está documentado :help sub-replace-special.

jamessan
fonte
6

Um NULbyte é um terminador de string em C e, por esse motivo, o Vim usa essa convenção, descrita no manual em :h NL-used-for-Nul:

<Nul> caracteres no arquivo são armazenados como <NL> na memória. Na tela, eles são mostrados como "^ @". A tradução é feita ao ler e gravar arquivos. Para combinar um <Nul> com um padrão de pesquisa, basta digitar CTRL- @ ou "CTRL-V 000". Provavelmente é exatamente o que você espera. Internamente, o caractere é substituído por um <NL> no padrão de pesquisa. O que é incomum é que digitar CTRL-V CTRL-J também insere um <NL>, assim também procura por um <Nul> no arquivo. {Vi não pode manipular <Nul> caracteres no arquivo}

Essa convenção se espalhou para o :s/.../.../comando, mas não para a substitute()função. \re \nnas cadeias de substituição nas substitute()chamadas mantêm seu significado original.

Eu não acho que haja razões mais profundas para qualquer um desses comportamentos. O Vim simplesmente evoluiu organicamente a partir do original vi. Nunca houve um grande plano para isso, os recursos foram empilhados um sobre o outro, com relativamente pouco esforço para mantê-los organizados.

Sato Katsura
fonte
0

Outros clones do Vi não suportam \rou \n(como uma barra invertida e letra reais) na substituição, mas o comportamento de um real ^M( CTRL-V Enter) que significa dividir a linha em duas linhas é o comportamento padrão :

Inserir um <carriage-return> no repl (que requer um <backslash> de escape no modo ex e um <control> -V de escape no modo aberto ou vi ) deve dividir a linha nesse ponto, criando uma nova linha no buffer de edição . O <retorno de transporte> deve ser descartado.

No arquivo Histórico do Unix, a primeira versão do BSD ex / vi aparece em 4.1cBSD ( @(#)ex_re.c 7.2 10/16/81e não está presente no 4BSD ( @(#)ex_re.c 6.2 10/23/80) [4.1a e 4.1b não estão presentes no arquivo].

O código relevante é:

/* ^V <return> from vi to split lines */
if (c == '\r')
    c = '\n';

Isso também é mencionado no arquivo de notícias :

Agora é possível dividir linhas com comandos substitutos do vi, usando ^ V <retorno> no rhs. Isso cuida da última boa razão para usar o modo de comando ex.

O comportamento anteriormente suportado no modo de comando ex era para a barra invertida-enter (ou seja, barra invertida seguida por uma nova linha real) para inserir uma nova linha.

Random832
fonte
0

A origem da assimetria remonta à história da computação.

Versão curta:

<CR> & <LF>  (Carriage-Return and Linefeed) 
== 
\r & \n

Versão longa:
as primeiras telas eram basicamente versões digitais de teletipos (TTY) e usavam códigos de controle para gerar um comportamento semelhante às impressoras. O retorno de carro levou o cursor (ou cabeça de impressão) para a coluna inicial. O avanço de linha avançou para a próxima linha (em uma tela) e alimentou o papel uma linha adiante.

Para impressoras, você precisava fazer um emparelhamento <CR><LF>ou sua saída não pareceria correta. Nas telas iniciais, o problema ainda era verdadeiro.

O DOS (e depois o Windows) seguiu o padrão antigo e salva o texto com <CRLF>.

* O texto NIX (como a maioria dos usuários do vi é familiar) usa apenas <LF>para obter eficiência.

Para testar no Windows, use o Word / Wordpad e salve algumas linhas de texto "como tipo: Texto - formato MS-DOS". Em seguida, abra o mesmo arquivo no bloco de notas. Deve parecer normal. Salve o mesmo arquivo no Word / Wordpad "como tipo: Texto". O bloco de notas ignorará todas as novas linhas e executará as linhas juntas. [O formato de texto do bloco de notas é padronizado para a \r\ncombinação, enquanto o Word / Wordpad é o padrão \n.]

\ r é o código equivalente a <CR>

\ n é o código equivalente a <LF>

E na minha experiência (muito limitada) com o vi, ele tentaria "consertar" a <CRLF>combinação do meu editor de texto do DOS. vi acabou removendo um caractere, substituindo por <NUL>. Grande parte do motivo pelo qual parei de usar o vi.

Robin
fonte
2
Embora toda a sua informação seja interessante, ela apenas diz por que \ré <CR>e \né <LF>. Não aborda a questão real de por que \n\rse comportar de maneira diferente em contextos diferentes.
precisa saber é o seguinte
Obrigado! :-) Eu estava mudando quando você respondeu. (Adicionado o último parágrafo.)
Robin