Vim/Buscas e substituições

Buscas

editar

Para fazer uma busca, certifique-se de que está em modo normal, pressione "/" e digite a expressão a ser procurada.

Para encontrar a primeira ocorrência de "foo" no texto:

/foo

Busca a palavra 'foo'

// 

Repete a última busca

/teste/+3

Posiciona o cursor três linhas após a ocorrência da palavra 'teste'

  • Para encontrar as próximas ocorrências, tecle "n".
  • Para encontrar as ocorrências anteriores, tecle "N".

Fazer buscas pelo valor hexadecimal de um caractere

 /\%x69   ...............  localiza a letra 'i' que em hexadecimal tem valor 069   


Dica: Um meio mais rápido para encontrar a próxima ocorrência de uma palavra sob o cursor, é teclar "*". Para encontrar uma ocorrência anterior da palavra sob o cursor, tecle "#". (Para isso, o cursor deve estar posicionado sobre a palavra que deseja procurar.)

Substituições

editar

Para fazer uma busca, certifique-se de que está em modo normal, em seguida digite use o comando ":s", conforme será explicado.

Para substituir "foo" por "bar" na linha atual:

:s/foo/bar

Para substituir "foo" por "bar" da primeira à décima linha do arquivo:

:1,10 s/foo/bar

Para substituir "foo" por "bar" da primeira à última linha do arquivo:

:1,$ s/foo/bar

Ou simplesmente:

:% s/foo/bar
$ ............. significa para o vim final do arquivo
% ............. representa o arquivo atual

O comando ":s" possui muitas opções que modificam seu comportamento.

Exemplos

editar
  • Busca usando alternativas:
/end\(if\|while\|for\)

Buscará "endif", "endwhile" e "endfor". Observe que é necessário "escapar" os caracteres \(, \| e \), caso contrário eles serão interpretados como caracteres comuns.

  • Quebra de linha
/quebra\nde linha
  • Ignorando maiúsculas e minúsculas
/\cpalavra
Usando \c o vim encontrará "palavra", "Palavra" ou até mesmo "PALAVRA"

Uma dica é colocar no seu arquivo de configuração 'vimrc' veja como editar preferências

set ignorecase ............... ignora maiúsculas e minúsculas na bucsca
set smartcase ................ se sua busca contiver maiúsculas ele passa a considera-las
set hlsearch ................. mostra o que está sendo buscado em cores
set incsearch ................ ativa a busca incremental

se você não sabe ainda como colocar estas preferências no arquivo de configuração pode ativa-las em modo de comando precedendo-as com dois pontos, assim:

:set ignorecase<enter>
  • Procurando palavras repetidas
/\<\(\w*\) \1\>

Um exemplo prático da expressão regular que elimine todas as linhas nas quais houver uma palavra

que se repita pelo menos uma vez, ou seja, mantenha apenas palavras que só aparecem uma vez.

Digamos que tenhamos o seguinte arquivo

1Apple 
1Apple 
2Peach 
2Peach 
2Peach 
3Beer 
4Banana 
4Banana 
4Banana 

A Solução seria

:%s/\v(.*)(\n\1)+//

Casando tudo .* seguido por uma quebra de linha \n, seguido pelo padrão precedente \1

  • Multilinha
/Hello\_s\+World

Buscará "Hello World", separados por qualquer número de espaços, incluindo quebras de linha. Buscará as três seqüências:

Hello World

Hello    World

Hello
World
  • Buscar linhas de até 30 caracteres de comprimento
/^.\{,30\}$
^ .............. representa começo de linha
  • Apaga todas as tags html/xml de um arquivo
:%s/<[^>]*>//g
  • Apaga linhas vazias
:%g/^$/d

Ou

:%s/^[\ \t]*\n//g 
  • Remover duas ou mais linhas vazias entre parágrafos diminuindo para uma só linha vazia.
:%s/\(^\n\{2,}\)/\r/g 

Você pode criar um mapeamento e colocar no seu ~/.vimrc

 map ,s <esc>:%s/\(^\n\{2,}\)/\r/g<cr>

No exemplo acima ',s' é um mapeamento para reduzir linhas em branco sucessivas para uma só

  • Remove não dígitos (não pega números)
:%s/^\D.*//g
  • Remove final de linha DOS/Windows ^M que tem código hexadecimal igual a '0d'
 :%s/\%x0d//g
  • Troca palavras de lugar usando expressões regulares
:%s/\(.\+\)\s\(.\+\)/\2 \1/    - troca palavras de lugar
  • Inserir numeração de linhas do arquivo
:%s/^/\=line('.'). ' '
  • Modificando todas as tags html para minusculo
:%s/<\([^>]*\)>/<\L\1>/g
  • move linhas 10 a 12 para além da linha 30
:10,12m30

O comando global 'g'

editar
  • buscando um padrao e gravandoo em outro arquivo
 :'a,'b g/^Error/ . w >> errors.txt

Para copiar linhas começadas com "Error" para o final do arquivo faça:

 :g/^Error/ copy $

Obs: O comando copy pode ser abreviado 'co' ou ainda você pode usar 't' para mais detalhes leia

   :h co

Entre as linhas que contiverem fred e joe substitua

 :g/fred/,/joe/s/isto/aquilo/gic

As opções 'gic' correspondem a global, ignore case e confirm, podendo ser omitidas deixando só o global

pegar caracteres numericos e jogar no final do arquivo?

 :g/^\d\+.*/m $

inverter a ordem das linhas do arquivo?

 :g/^/m0

apagar as linhas que contém "Line commented"

 :g/Line commented/d

copiar determinado pardrão para um registro

 :g/pattern/ normal "Ayy

copiar linhas que contém um padrão e a linha subsequênte para o final

 :g/padrão/;+1 copy $
Reordenando parágrafos
editar

Digamos que você tenha um arquivo com o seguinte conteúdo

\begin{rSubsection}{Example 1}{}{Redacted}{}
\item Stuff I did 
\item Also did other things 
\end{rSubsection} 

\begin{rSubsection}{Example 2}{}{Redacted}{} 
\item Stuff I did 
\item Also did other things 
\end{rSubsection} 

\begin{rSubsection}{Example 3}{}{Redacted}{} 
\item Stuff I did 
\item Also did other things 
\end{rSubsection} 

\begin{rSubsection}{Example 4}{}{Redacted}{} 
\item Stuff I did 
\item Also did other things 
\end{rSubsection} 

Para reordenar esses blocos de modo que o 4º bloco fique no começo e o bloco 1 fique no final

fazemos o seguinte:

Adicionamos uma linha ao final do arquivo

:$put _

Em seguida executamos o seguinte comando global

:g/Example [2-4]/normal! dapggP

Na prática o vim moverá os blocos 2 a 4 para o começo usando o comando "normal" dap (delete parágrafo)

gg que salta para o começo do arquivo e o comando de colar P.

Para colocar a última busca em uma substituição faça:

 :%s/Control-r//novo/g

A dupla barra corresponde ao ultimo padrão procurado, e portanto o comando abaixo fará a substituição da ultima busca por casinha

 :%s//casinha/g

Filtrando arquivos com o vimgrep

editar

Por vezes sabemos que aquela anotação foi feita, mas no momeno esquecemos em qual arquivo está, no exemplo abaixo procuramos a palavra dicas à partir da nossa pasta pessoal pela palavra 'dicas' em todos os arquivos com extensão 'txt'

~/ ............ equivale a /home/user
:lvimgrep /dicas/ ~/**/*.txt | ls

O comando

Copiar a partir de um ponto

editar
 :19;+3 co $

O vim sempre necessita de um intervalo (inicial e final) mas se você usar ';' ele considera a primeira linha como segundo ponto do intervalo, e no caso acima estamos dizendo (nas entrelinhas) linhas 19+3

De forma hanáloga podemos usar como referência um padrão qualquer

:/palavra/;+10 m 0

O comando acima diz: à partir da linha que contém 'palavra' incluindo as 10 próximas linhas mova 'm' para a primeira linha '0', ou seja antes da linha 1.

Dicas das lista vi-br

editar
Fonte: http://groups.yahoo.com/group/vi-br/message/853
Problema:
Essa deve ser uma pergunta comum.
Suponha o seguinte conteúdo de arquivo:

... // várias linhas
texto1000texto    // linha i
texto1000texto    // linha i+1
texto1000texto    // linha i+2
texto1000texto    // linha i+3
texto1000texto    // linha i+4
... // várias linhas

Gostaria de um comando que mudasse para

... // várias linhas
texto1001texto    // linha i
texto1002texto    // linha i+1
texto1003texto    // linha i+2
texto1004texto    // linha i+3
texto1005texto    // linha i+4
... // várias linhas

Ou seja, somasse 1 a cada um dos números entre os textos especificando como range as linhas i,i+4

:10,20! awk 'BEGIN{i=1}{if (match($0, "[0-9]+")) print "texto"
(substr($0, RSTART, RLENGTH) + i++) "texto"}'

Mas muitos sistemas não tem awk, e logo a melhor solução mesmo é usar o vim:

:let i=1 | 10,20 g/texto\d\+texto/s/\d\+/\=submatch(0)+i/ | let i=i+1

Observação: 10,20 é o intervalo, ou seja, da linha 10 até a linha 20

Para maiores informações sobre buscas e substituições:

:help /
:help :s
:help pattern

Dicas do dicas-l

editar

Junção de linhas com vim

editar

Colaboração: Rubens Queiroz de Almeida

Recentemente precisei combinar, em um arquivo, duas linhas consecutivas. O arquivo original continha linhas como

 Matrícula: 123456
 Senha: yatVind7kned
 Matrícula: 123456
 Senha: invanBabnit3

E assim por diante. Eu precisava converter este arquivo para algo como:

 Matrícula: 123456 - Senha: yatVind7kned
 Matrícula: 123456 - Senha: invanBabnit3

Para isto, basta emitir o comando:

 :g/^Matrícula/s/\n/ - /

Explicando:

g/^Matrícula 	busca, no arquivo inteiro (g) pela palavra Matrícula na primeira coluna
s/\n/ - / 	substitui a quebra de linha (\n), pelos caracteres ** - **. 
"Esta substituição faz a junção das duas linhas adjacentes