Supondo que seu arquivo tenha menos de 20.000 linhas, é claro :-)
paxdiablo
3
Na verdade você está errado Michael. Isso funciona perfeitamente, pois o VI interromperá a execução da macro assim que atingir o final do arquivo. Você pode experimentá-lo facilmente com o exemplo acima.
rui
1
Bem, como qualquer macro, você precisa acertar na primeira vez, mas depois disso você pode aplicar a qualquer arquivo apenas digitando 10000 @ q. De qualquer forma, acredito que seja apenas uma questão de gosto, então definitivamente não vou iniciar um debate filosófico. :)
rui
3
Eu prefiro usar 'macro'. Usando macro, você 'descreve' como resolveria uma tarefa em particular e deixa o VIM repeti-la para você. RUI, prefiro usar 'j' em vez da tecla de seta.
Uma forma elegante (e eficiente) de realizar a tarefa é invocar o :+deletecomando removendo a linha seguinte à atual, em cada linha usando o :globalcomando:
Por que essa resposta não obteve mais votos positivos? Isso é tão limpo e simples. Alternativamente, você pode excluir a primeira linha e executar o comando acima para excluir todas as linhas ímpares.
Usagi
3
@Usagi: Obrigado! Eu sinto a mesma coisa sobre isso. E sim, você está absolutamente certo, :1d|g/^/+dexclui as linhas ímpares.
ib.
@Usagi A outra resposta foi selecionada como a 'melhor resposta' 2 anos antes de sua resposta aparecer. Além disso, embora esta seja uma solução mais elegante, ela poderia ter sido escrita de uma maneira mais útil (ou seja, não há menção do que ^ faz, embora a macro seja fácil de entender).
user1271772
3
Desculpe, mas sem uma explicação de como aquele comando executa o comportamento desejado, eu não votaria contra ele e prefiro a resposta aceita, pois entendo como ele atinge o objetivo. É a diferença entre dar um peixe a um homem e ensiná-lo a pescar.
Gabe
3
Não sei, essa resposta me fez sair e aprender a pescar com o comando: g (isto é, me fez google esta página - vim.wikia.com/wiki/Power_of_g ).
snetch de
67
Podemos usar :normalou :normpara executar determinados comandos de modo normal. Fonte.
Essa resposta não recebe atenção suficiente, possivelmente por causa da falta de explicação aqui e na folha de dicas vinculada e confusa. o comando norm executa os comandos do modo normal equivalentes às letras que o seguem. Portanto, aqui está executando j para mover uma linha para baixo e dd para excluí-lo. Isso é generalizável para a linha X, adicionando mais 'j's neste caso.
imoatama
5
e% é uma abreviação de 1, $ (execute o seguinte comando da linha 1 até o final)
Lambart
3
Estou interessado em %norm ddjsaber por que não funciona se você deseja excluir linhas estranhas.
Cyker
10
:map ^o ddj^o
^o
Aqui ^ significa CTRL. Macro recursiva para excluir uma linha a cada duas linhas. Escolha bem sua primeira linha e pronto.
Então eu prefiro !perl -ne 'print unless $. % 2':-)
Alex Brasetvik
E, Alex, eu definitivamente preferiria minha solução à sua, mas vale a pena considerar esta, pois é a única solução sensata usando apenas o próprio vim aqui.
Michael Krelin - hacker de
O modo macro é muito mais fácil.
trusktr de
+1 por causa da flexibilidade com a if (expression)qual também funciona para cada terceira linha etc.
Jens
5
Você sempre pode canalizar um comando shell, o que significa que você pode usar qualquer linguagem de script que desejar:
:%!perl -nle 'print if $. % 2'
(ou use "a menos" em vez de "se", dependendo de quais linhas você deseja)
Você não precisa -lmudar para Perl ... também, eu diria que awké um pouco mais difundido do que Perl, embora não seja muito mais hoje em dia, e possa fazer isso mais curto:, :%!awk NR\%2ou :%!awk 1-NR\%2para as outras linhas.
Certo. Porque eu esqueci disso. ;-) Mas na verdade, a variante "apropriada" será ainda mais longa com o NR. E não haveria duas contrapartes bonitas .
Michael Krelin - hacker de
:%!awk NR\%2ou :%!awk 1-NR\%2, como postei em outro comentário. Isso dificilmente é mais longo.
efêmero
1
1-NRé mais longo que c++. Sim, eu sei que é um personagem. Como eu disse - a verdadeira razão é que me esqueci disso. Enfim, parece que as pessoas não apreciam a beleza do awk aqui.
Michael Krelin - hacker de
E NRé mais curto que ++c:)
efêmero de
3
Você pode usar os recursos de pesquisa e substituição do próprio Vim, como: Coloque o cursor na primeira linha e digite no modo normal:
:.,/fff/s/\n.*\(\n.*\)/\1/g
O .,/fff/é o intervalo para a substituição. Significa "desta linha para a linha que corresponde ao regex fff(neste caso, a última linha).
s///é o comando substituto. Ele procura um regex e substitui todas as ocorrências dele por uma string. O gno final significa repetir a substituição enquanto a regex continuar sendo encontrada.
A regex \n.*\(\n.*\)corresponde a uma nova linha, depois a uma linha inteira ( .*corresponde a qualquer número de caracteres, exceto a uma nova linha), a outra nova linha e a outra linha. Os parênteses \(e \)fazem com que a expressão dentro deles seja gravada, para que possamos usá-la mais tarde usando \1.
\1 insere a nova linha agrupada e a linha depois dela de volta, porque não queremos que a próxima linha também vá - queremos apenas que o mecanismo de substituição passe por ela, para não excluí-la na próxima substituição.
Desta forma, você pode controlar o intervalo em que deseja que a exclusão ocorra e não precisa usar nenhuma ferramenta externa.
b = cb[:]copia temporariamente todas as linhas do buffer atual para b. b[::2]obtém cada segunda linha do buffer e as atribui a todo o buffer atual cb[:]. A cópia para bé necessária, pois os objetos de buffer não parecem oferecer suporte à sintaxe de fatia estendida.
Este provavelmente não é o "jeito do vim", mas pode ser mais fácil de lembrar se você conhecer o python.
Para excluir linhas ímpares (1,3,5, ..) -> :%s/\(.*\)\n\(.*\)\n/\2\r/g
Para excluir linhas pares (2,4,6, ..) -> :%s/\(.*\)\n.*\n/\1\r/g
Pesquise o texto (forma a primeira linha) seguido por um caractere de nova linha e um pouco mais de texto (forma a segunda linha) seguido por outro caractere de nova linha e substitua o acima pela primeira correspondência (linha ímpar) ou segunda correspondência (linha par) seguido por retorno de carro.
:% !sed -e '2~2 d'
^^^^ pipe file through a shell command
^^^^^^ the command is sed, and -e describes an expression as parameter
^^^^^ starting with the second line, delete every second line
Respostas:
Você pode usar uma macro para isso. Faça o seguinte.
gg
.qq
.dd
depois.q
.10000@q
PS: Para ir para o modo de comando, pressione Escape algumas vezes.
fonte
:g/^/+d
do usuário stackoverflow.com/users/254635/ib (abaixo) é uma maneira mais elegante de resolver isso.Uma forma elegante (e eficiente) de realizar a tarefa é invocar o
:+delete
comando removendo a linha seguinte à atual, em cada linha usando o:global
comando:fonte
:1d|g/^/+d
exclui as linhas ímpares.Podemos usar
:normal
ou:norm
para executar determinados comandos de modo normal. Fonte.fonte
%norm ddj
saber por que não funciona se você deseja excluir linhas estranhas.Aqui ^ significa CTRL. Macro recursiva para excluir uma linha a cada duas linhas. Escolha bem sua primeira linha e pronto.
fonte
do arquivo de correio vim :
(Para ser digitado em uma linha na linha de comando do vim, excluirá a linha 1,3,5,7, ...)
fonte
!perl -ne 'print unless $. % 2'
:-)if (expression)
qual também funciona para cada terceira linha etc.Você sempre pode canalizar um comando shell, o que significa que você pode usar qualquer linguagem de script que desejar:
(ou use "a menos" em vez de "se", dependendo de quais linhas você deseja)
fonte
-l
mudar para Perl ... também, eu diria queawk
é um pouco mais difundido do que Perl, embora não seja muito mais hoje em dia, e possa fazer isso mais curto:,:%!awk NR\%2
ou:%!awk 1-NR\%2
para as outras linhas.alternativamente
dependendo de qual metade você deseja eliminar.
fonte
NR
variável existente ?:%!awk NR\%2
ou:%!awk 1-NR\%2
, como postei em outro comentário. Isso dificilmente é mais longo.1-NR
é mais longo quec++
. Sim, eu sei que é um personagem. Como eu disse - a verdadeira razão é que me esqueci disso. Enfim, parece que as pessoas não apreciam a beleza do awk aqui.NR
é mais curto que++c
:)Você pode usar os recursos de pesquisa e substituição do próprio Vim, como: Coloque o cursor na primeira linha e digite no modo normal:
.,/fff/
é o intervalo para a substituição. Significa "desta linha para a linha que corresponde ao regexfff
(neste caso, a última linha).s///
é o comando substituto. Ele procura um regex e substitui todas as ocorrências dele por uma string. Og
no final significa repetir a substituição enquanto a regex continuar sendo encontrada.\n.*\(\n.*\)
corresponde a uma nova linha, depois a uma linha inteira (.*
corresponde a qualquer número de caracteres, exceto a uma nova linha), a outra nova linha e a outra linha. Os parênteses\(
e\)
fazem com que a expressão dentro deles seja gravada, para que possamos usá-la mais tarde usando\1
.\1
insere a nova linha agrupada e a linha depois dela de volta, porque não queremos que a próxima linha também vá - queremos apenas que o mecanismo de substituição passe por ela, para não excluí-la na próxima substituição.Desta forma, você pode controlar o intervalo em que deseja que a exclusão ocorra e não precisa usar nenhuma ferramenta externa.
fonte
$
vez de/fff/
, para o fim do arquivo, independentemente do conteúdo do arquivo.Como outra abordagem, você também pode usar python se seu vim tiver suporte para ele.
b = cb[:]
copia temporariamente todas as linhas do buffer atual parab
.b[::2]
obtém cada segunda linha do buffer e as atribui a todo o buffer atualcb[:]
. A cópia parab
é necessária, pois os objetos de buffer não parecem oferecer suporte à sintaxe de fatia estendida.Este provavelmente não é o "jeito do vim", mas pode ser mais fácil de lembrar se você conhecer o python.
fonte
Para excluir linhas ímpares (1,3,5, ..) ->
:%s/\(.*\)\n\(.*\)\n/\2\r/g
Para excluir linhas pares (2,4,6, ..) ->
:%s/\(.*\)\n.*\n/\1\r/g
Pesquise o texto (forma a primeira linha) seguido por um caractere de nova linha e um pouco mais de texto (forma a segunda linha) seguido por outro caractere de nova linha e substitua o acima pela primeira correspondência (linha ímpar) ou segunda correspondência (linha par) seguido por retorno de carro.
fonte
Invoque sed:
fonte
solução
você pode tentar isso no vim
editar
Vou tentar ser mais claro (duas partes)
primeira parte do intervalo de seleção (
:from,to
)segunda parte da ação (
d
deletar):1,$-1
)g
) delete (+1d
) próxima linhavocê pode tentar mover para a primeira linha do seu arquivo e executar
:+1d
você verá a próxima linha desaparecerEu sei que está lamacento, mas é vim e funciona
fonte