Eu tenho uma lista de arquivos:
./a.temp.txt ./a.temp.txt
./a/b.temp.txt ./a/b.temp.txt
./a/b/c.temp.txt ./a/b/c.temp.txt
E eu quero remover o temp.
em cada linha, mas apenas a segunda ocorrência , assim, o arquivo deve se parecer com:
./a.temp.txt ./a.txt
./a/b.temp.txt ./a/b.txt
./a/b/c.temp.txt ./a/b/c.txt
Como devo fazer isso?
Respostas:
Em geral, você pode corresponder à enésima ocorrência de algo usando
\zs
e\{N}
. Há um exemplo dado em:help \zs
.No seu caso, o comando seria:
fonte
%s/\v(.{-}\zstemp.){2}//
Isso é muito mais fácil com
sed
:Com o Vim, você precisa de uma correspondência não gananciosa, e não é fácil estender o método para substituir a 3ª, 4ª, etc. ocorrência de
temp
. Mas isso pode ser feito se você insistir:fonte
sed
aplica scripts a cada linha de entrada por vez.sed
da mesma maneira que pode canalizá-las para qualquer outro programa. Fi::%!sed 's/\.temp\././2'
.sed
em UNIX-friendly, lê entrada destdin
e grava resultados parastdout
.Você também pode fazer isso com um olhar para trás.
Se você deseja remover TODAS as ocorrências após a primeira, você pode anexar a
g
sinalização no final.\(\)\@<=
Irá procurar por qualquer padrão entre\(
e\)
mas não adicionará o texto encontrado à correspondência.Veja
:h \@<=
para mais informações.fonte
Você pode usar uma macro como o @Meshpi já sugerido. Mas, essa é outra maneira de realizar a mesma coisa.
E então você pode repetir até o fim. E haverá muito mais maneiras de fazer o mesmo.
fonte
Essa solução é semelhante à do TessellatingHeckler, mas é mais facilmente adaptada a qualquer padrão que precise ser excluído.
Veja como funciona:
:g/temp\./
para cada linha correspondente a "temp".normal
execute o seguinte no modo normal2n
encontre a segunda ocorrência do padrãogn
selecioned
e exclua-o.Isso funcionará para qualquer padrão dado
:g
.normal
pode ser abreviado paranorm
.gnd
é equivalente adgn
. Edit: Na verdade,2ngnd
é equivalente ad2gn
.Veja o Vim Tips Wiki para mais exemplos do comando global.
fonte
No Vim, você pode definir a coluna antes / depois / após a qual deseja que sua correspondência ocorra
:help \%c
:Isso eliminará todos os itens
.temp
encontrados após a coluna 17 de todas as linhas no buffer atual.Nota 1:
/g
não é necessário com a sua amostra.Nota 2: Eu uso esse recurso útil muitas vezes com o qmv . Recomendado!
fonte
vidir
evipe
no pacote moreutils .Isso é realmente muito simples. Para coincidir com a segunda temperatura, permita qualquer coisa seguida por "temp" seguida por qualquer coisa e procure temp novamente.
Os
\zs
meios "Iniciar a seleção aqui" para que a primeira parte da partida (tudo antes da segunda temperatura) não sejam removidos. Na verdade, é um recurso extremamente útil que acabei de aprender! Sem ele, o regex teria que ficar assim:fonte
temp
em uma linha, sua receita excluirá a última, e não a segunda. Culpe a ganância. :)My case was to match old filename to new filename, so only 2 occurrences will be on each line. And only the second one should change
.Em vez de regex, eu iria com um comando que faz:
temp
e execute-o em todas as linhas:
NB
^[
é especial e representa pressionar a tecla Escape; você digita com:Ctrl-q <Esc>
Mas uma opção regex, que eu acho que não foi sugerida ainda, é corresponder
temp.
seguida por qualquer coisa, exceto a.
, ancorada no final da linha.Que corresponderá
temp.txt
ao final de uma linha e a substituirá por apenas umtxt
pouco.fonte
Eu escreveria uma macro com o cursor começando no canto superior esquerdo.
qq4f.dfpq
Depois, selecionava o restante das linhas usando
V
e executava a macro nessas linhas com:'<,'>norm!@q
Isso só funcionará se o formato do texto permanecer o mesmo em relação ao número de pontos antes da segunda temperatura.
fonte
n
vez disso,4f.
se um nome de arquivo tiver mais pontos, sua macro poderá falhar ou excluir itens que não devem ser excluídos.Não há nada que impeça o uso de duas expressões regulares em vez de apenas uma, ou seja, altere a primeira ocorrência e depois troque as colunas:
Pode não ser muito inteligente, mas acho muito legível.
fonte
Minha tentativa
fonte