Você precisa de substituição por um estado. Lembro-me de ter fornecido uma (/ várias?) Solução completa para esse tipo de problemas no SO.
Aqui está outra maneira de proceder (1). Agora, vou prosseguir em 2 etapas:
- uma variável de lista fictícia que preciso para o truque sujo e complicado que vou empregar
- uma substituição na qual insiro o len desse array fictício que estou preenchendo em cada ocorrência correspondente.
Que dá:
:let t=[]
:%s/#\zs\d\+\(\.\d\+\)\=\ze/\=len(add(t,1))/g
Se você não está acostumado a vim regexes, eu uso :h /\zse \zepara especificar qual sub-padrão eu estou correspondendo, então eu correspondo a uma série de dígitos possivelmente seguidos por um ponto e outros dígitos. Isso não é perfeito para nenhum número de ponto flutuante, mas é o suficiente aqui.
Nota: Você precisará agrupá-lo em uma função dupla + comando para uma interface simples. Novamente, existem exemplos no SO / vim ( aqui , aqui , aqui ) Atualmente, conheço o suficiente do vim para não me importar em envolver esse truque em um comando. Na verdade, poderei escrever este comando na primeira tentativa, enquanto levarei alguns minutos para lembrar o nome do comando.
(1) O objetivo é poder manter um estado entre substituições e substituir a ocorrência atual por algo que dependa do estado atual.
Graças a :s\=nós somos capazes de inserir algo resultante de uma computação.
Continua sendo o problema do estado. Ou definimos uma função que gerencia um estado externo ou nos atualizamos como um estado externo. Em C (e idiomas relacionados), poderíamos ter usado algo como length++ou length+=1. Infelizmente, nos scripts do vim, +=não pode ser usado imediatamente. Ele precisa ser usado com :setou com :let. Isso significa que :let length+=1incrementa um número, mas não retorna nada. Nós não podemos escrever :s/pattern/\=(length+=1). Precisamos de outra coisa.
Precisamos de funções mutantes. ou seja, funções que modificam suas entradas. Temos setreg(), map(), add()e provavelmente mais. Vamos começar com eles.
setreg()muda um registro. Perfeito. Podemos escrever setreg('a',@a+1)como na solução do @Doktor OSwaldo. E, no entanto, isso não é suficiente. setreg()é mais um procedimento do que uma função (para aqueles que conhecem Pascal, Ada ...). Isso significa que não retorna nada. Na verdade, ele retorna algo. Saída nominal (ou seja , saídas não-excepcionais ) sempre retorna algo. Por padrão, quando esquecemos de retornar algo, 0 é retornado - isso também se aplica às funções internas. É por isso que em sua solução a expressão de substituição é realmente \=@a+setreg(...). Complicado, não é?
map()também pode ser usado. Se começarmos de uma lista com um único 0 ( :let single_length=[0]), poderemos incrementá-la graças a map(single_length, 'v:val + 1'). Então precisamos retornar o novo comprimento. Ao contrário setreg(), map()retorna sua entrada mutada. Perfeito, o comprimento é armazenado na primeira (e única e, portanto, última) posição da lista. A expressão de substituição pode ser \=map(...)[0].
add()é o que eu costumo usar por hábito (eu pensei sobre isso map()na verdade, e ainda não participei das respectivas apresentações). A idéia add()é usar uma lista como o estado atual e acrescentar algo no final antes de cada substituição. Costumo armazenar o novo valor no final da lista e usá-lo para a substituição. Como add()também retorna a sua lista de entrada mutante, podemos usar: \=add(state, Func(state[-1], submatch(0)))[-1]. No caso do OP, precisamos apenas lembrar quantas correspondências foram detectadas até o momento. Retornar o comprimento dessa lista de estados é suficiente. Daí meu \=len(add(state, whatever)).
perldo, você pode usar:%perldo s/#\K\d+(\.\d+)?/++$i/ge