状態による代替が必要です。SOでのこの種の問題に対して(/いくつか?)完全なソリューションを提供したことを覚えています。
次に進む別の方法を示します(1)。次に、2つのステップに進みます。
- 私が使用するダーティで複雑なトリックに必要なダミーリスト変数
- このダミー配列のlenを挿入する置換で、一致する各出現箇所に入力します。
それは与える:
:let t=[]
:%s/#\zs\d\+\(\.\d\+\)\=\ze/\=len(add(t,1))/g
vim正規表現に慣れていない場合は、とを使用:h /\zs
し\ze
て、照合するサブパターンを指定します。その後、一連の数字とそれに続くドットやその他の数字を照合します。これはどの浮動小数点数にも完全ではありませんが、ここではこれで十分です。
注:シンプルなインターフェースの場合は、それを2つの関数+コマンドでラップする必要があります。ここでも、SO / vim(here、here、here)の例があります。最近では、このトリックをコマンドにラップすることを気にしないほど十分なvimを知っています。確かに、最初の試行でこのコマンドを書くことができますが、コマンドの名前を覚えるのに数分かかります。
(1)目的は、置換の間の状態を維持し、現在の発生を現在の状態に依存するものに置き換えることです。
おかげで:s\=
、計算から生じた何かを挿入することができます。
状態の問題のままです。外部状態を管理する関数を定義するか、外部状態を更新します。C(および関連言語)では、length++
またはのようなものを使用できたはずlength+=1
です。残念ながら、vimスクリプトで+=
は、そのままでは使用できません。:set
またはとともに使用する必要があります:let
。つまり:let length+=1
、数値をインクリメントしますが、何も返しません。書けません:s/pattern/\=(length+=1)
。他に何かが必要です。
変異機能が必要です。つまり、入力を変更する関数です。我々は持っているsetreg()
、map()
、add()
おそらくより。それらから始めましょう。
setreg()
レジスタを変更します。完璧です。setreg('a',@a+1)
@Doktor OSwaldoのソリューションのように書くことができます。それでも、これでは不十分です。setreg()
(パスカル、エイダを知っている私たちの間で...)関数よりも手続きの詳細です。つまり、何も返されません。実際には、それは何かを返します。名目上の出口(つまり、例外でない出口)は常に何かを返します。デフォルトでは、何かを返すのを忘れた場合、0が返されます。これは、組み込み関数にも適用されます。そのため、彼のソリューションでは置換式は実際に\=@a+setreg(...)
です。トリッキーですね。
map()
使用することもできます。0(:let single_length=[0]
)が1つのリストから開始する場合、のおかげでそれを増やすことができますmap(single_length, 'v:val + 1')
。次に、新しい長さを返す必要があります。とは異なりsetreg()
、map()
変化した入力を返します。それは完璧です、長さはリストの最初の(そして一意の、したがって最後の)位置に保存されます。置換式はである可能性があります\=map(...)[0]
。
add()
私がよく使う習慣の1つです(map()
実際、私は実際に行ったことがありますが、それぞれのパフォーマンスのベンチマークはまだ行っていません)。のアイデアadd()
は、現在の状態としてリストを使用し、各置換の前に最後に何かを追加することです。私はよく新しい値をリストの最後に保存し、置換に使用します。変更されadd()
た入力リストも返すので、次のものを使用できます\=add(state, Func(state[-1], submatch(0)))[-1]
。OPの場合、これまでに検出された一致の数を覚えておけば十分です。この状態リストの長さを返すだけで十分です。したがって、私の\=len(add(state, whatever))
。
perldo
、使用できます:%perldo s/#\K\d+(\.\d+)?/++$i/ge