Vim - Adicionando linha vazia entre linhas

15

Como insiro uma linha em branco entre todas as linhas que não estão em branco?

por exemplo. a partir de

line 1
line 2
line 3

line 4
line 5

para

line 1

line 2

line 3

line 4

line 5
ayutheos
fonte

Respostas:

27

O comando g do Vim foi projetado para exatamente esse tipo de tarefa; executando uma única ação em cada linha que corresponda a um padrão específico. Aqui está a minha resposta:

:g/.\n\n\@!/norm o

O padrão que eu uso é /.\n\n\@!/. Dividindo isso em seus componentes:

  • .Corresponde a qualquer caractere na linha. (usado para descartar imediatamente qualquer linha vazia existente da consideração)
  • \n Corresponde a um \ n no final do caractere acima
  • \n\@! Falha na partida se houver outro \ n imediatamente após o anterior \ n.

(Verifique :h E59para obter mais informações \@!e especificadores de correspondência semelhantes em expressões regulares - também existem outros!)

Portanto, a regex do comando: g agora selecionou todas as linhas não vazias que são finalizadas por uma única nova linha e que não são seguidas por uma linha vazia.

Após o padrão em uma :ginstrução, vem o comando para executar nas linhas correspondentes. Nesse caso, eu disse para executar um comando no modo normal (abreviado para norm), e o comando a ser executado é simplesmente o, que insere uma linha vazia abaixo da linha atual.

Então, juntos, o comando encontra todas as linhas que não possuem uma linha vazia abaixo e adiciona uma. E é só isso! Você pode verificar o artigo Power of G do wiki do vim para obter coisas mais sofisticadas com as quais você pode fazer :g(e é irmã negativa :v) - é um daqueles comandos incrivelmente úteis nos quais você logo confia e depois sente muita falta de editores que não tem.

Trevor Powell
fonte
11
Precisamente. Eu costumo procurar por taquigrafia, :%norm omas acontece que isso não funciona como planejado no caso de o. +1
veja
Digite :%s/$/, pressione e ^V, em seguida, pressione Enter.
jpaugh
11
@jpaugh Supondo que você queira dizer :%s/$/<C-V><CR><CR>(usar a codificação vim-folk comum de pressionamentos de tecla), essa abordagem apenas adiciona uma nova linha após cada linha. Ou seja, linhas que já estão separadas por espaços em branco (consulte Linha 3 -> Linha 4, no texto de exemplo) acabam recebendo linhas em branco extras. A pergunta original era evitar adicionar linhas em branco extras onde elas já existiam no texto inicial.
Trevor Powell
3

Quando testei a pesquisa global e a resposta de substituição do @ NeilForester, descobri que ela perdia a cada segundo a substituição pretendida em linhas consecutivas que não estavam em branco se as linhas tivessem apenas um caractere em cada. Parece que o padrão começa a corresponder em cada ocasião após o último caractere correspondente à ocasião anterior.

Usar lookbehind e lookahead resolve esse problema e torna o regex um pouco mais curto também:

:%s/\n\@<!\n\n\@!/\r\r/g
Simon
fonte
Obrigado! Isso funciona e não adiciona mais linhas se eu executar a pesquisa novamente (se, por exemplo, adicionei novas linhas ao meu arquivo).
11
Você poderia explicar o que significa cada expressão regular no padrão de pesquisa? Olhando para a ajuda do vim, \n\@<!\nsignifica que qualquer quebra de linha que não está logo após outra quebra de linha está correto? Mas eu não conseguia entender o que \n\@!significa. Eu gostaria de entender isso para que eu possa aprender e aplicá-la a outros padrões de pesquisa :)
Sim, \n\@<!\nsignifica qualquer quebra de linha que não segue imediatamente outra quebra de linha. \n\@!corresponde à largura zero se o átomo anterior (ie \n) não corresponder logo antes do que segue. Tente :help \@<!ver a documentação sobre isso no vim. I
Simon
3

Outra maneira:

%s/\(.\)\n\(.\)/\1\r\r\2/

Que significa,

\(.\) match and capture a non-newline character,
\n    match a newline
\(.\) match and capture a non-newline character

substitua por: primeira captura, novas linhas duplas e a segunda captura.

Por exemplo, line1\nLine2resulta em \1 = 1e \2 = L.

perreal
fonte
0

Corrija-me se eu estiver errada. Acredito que você use a letra k no modo de comando para mover uma linha para baixo. Em seguida, entre no modo de inserção e adicione a próxima linha. Repita conforme necessário? Espero que isto ajude!

Nick Gerrer
fonte
ksobe uma linha. jdesce uma linha.
Neil Forrester
Sim, é verdade. Meu erro. Obrigado Neil!
0
/[^\n]\n[^\n]
:map <F2> no<esc><F2>

Então pressione <F2>. Isso pesquisará duas linhas consecutivas que não estiverem em branco e, em seguida, adicionará uma linha entre elas, repetidamente.

Editar:

Aqui está uma maneira alternativa de fazer isso com uma única pesquisa global e substituir:

:%s/\([^\n]\)\n\([^\n]\)/\1\r\r\2/g
Neil Forrester
fonte
Meu arquivo tem muitas linhas. Existe uma maneira de fazer uma pesquisa regex e inserir linha em branco para o arquivo inteiro? Eu estive olhando para stackoverflow.com/questions/2673209/…, mas não conseguia entender o que todos os comandos regex significam.
Veja minha edição acima para uma maneira alternativa de realizar a mesma coisa em um único comando e sem um mapeamento recursivo. A primeira maneira deve funcionar para todo o arquivo.
Neil Forrester
0

Tente este comando ( 16caracteres):

:%!sed G|cat -s
kev
fonte
Em vez de tentar "vimgolf" um comando curto, uma pequena explicação das opções bastante obscuras usadas seria mais útil.
Ingo Karkat
0

Não sei quanto tempo dura o seu arquivo, mas um dos métodos mais simples é digitar ono modo de comando. E na próxima linha .. Isso pode ser carregado para uma macro simples.

Demagogo
fonte