Compreendendo as diferenças de referência de linha através de: g / ^ / norm e através de:% norm

8

Digamos que eu tenho o seguinte arquivo muito simples

a
b
c
d
e

e decidi que quero adicionar linhas vazias após cada linha. Vários métodos diferentes imediatamente saltam à minha mente. Podemos apenas fazê-lo (e assim abraçar o fracasso). Podemos gravar uma macro como qqo<ESC>jqe repeti-la várias vezes.

Dois outros métodos pareciam mais óbvios para mim na época.

Em primeiro lugar, pensei em emitir o :normcomando oem cada linha. Então eu corro :%norm o. Mas o que realmente acontece é que obtemos 5 linhas em branco, seguidas pelas linhas não separadas, como acima. Interpreto que isso significa que %norm, por meio do vim, na verdade, a mensagem é exibida com o seguinte comando normal nas cinco primeiras linhas desse arquivo de cinco linhas . O ocomando cria uma nova linha e o vim é "burro" no sentido de que faz referência pelo número da linha e não por algum outro identificador.

Bem, eu estava envergonhado. Certo. Tentei algumas outras coisas para ver se conseguia fazer o método acima funcionar, mas, infelizmente, não consegui. Por curiosidade, tentei meu outro método favorito de aplicação em massa. Isso me levou a tentar :g/^/norm o. Para minha surpresa, isso funciona muito bem! Então, aos meus olhos, parece que o vim não é "burro" aqui da mesma maneira que acima e faz referência a linhas por mais do que apenas o número da linha.

O que exatamente está acontecendo?

davidlowryduda
fonte
2
Em uma nota lateral: você também pode fazê-lo como este: :%s/$/\r/ou assim: :%s/\n/\r\r/. O argumento é que as novas linhas podem ser correspondidas \n, mas precisam ser escritas como \rnos valores de substituição.
Lcd047 17/07/2015

Respostas:

9

Bem, %é uma abreviação de 1,$(um intervalo da primeira linha à última). De :he :%:

Line numbers may be specified with:             :range E14 {address}
        {number}        an absolute line number
        .               the current line                          :.
        $               the last line in the file                 :$
        %               equal to 1,$ (the entire file)            :%

E para :global:

The global commands work by first scanning through the [range] lines and
marking each line where a match occurs (for a multi-line pattern, only the
start of the match matters).
In a second scan the [cmd] is executed for each marked line with its line
number prepended.  For ":v" and ":g!" the command is executed for each not
marked line.  If a line is deleted its mark disappears.

Portanto, o primeiro caso é como percorrer uma lista enquanto a modifica, portanto, um contador nos elementos da lista se torna inválido. No segundo caso, marcamos os elementos que queremos segmentar em uma passagem, de modo que, mesmo que a lista seja modificada na segunda passagem, ainda sabemos em quais elementos queremos trabalhar.

muru
fonte
Ah, está até no arquivo de ajuda para global. Como sou boba. Obrigado
davidlowryduda
homem - g é um exagero louco útil. tenho que gastar mais tempo para passar do usuário vi médio para o usuário avançado
javadba