在Vim中搜索并替换为递增的值
假设我编写了一个简单的CSS规则,如下所示:在Vim中搜索并替换为递增的值,vim,replace,Vim,Replace,假设我编写了一个简单的CSS规则,如下所示: .star_10 { background: url(stars.png) no-repeat 0 0; } .star_10 { background: url(stars.png) no-repeat 0 0; } .star_9 { background: url(stars.png) no-repeat 0 -18px; } .star_8 { background: url(stars.png) no-repeat 0 -
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_9 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_8 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_7 {
background: url(stars.png) no-repeat 0 -54px;
}
what 0 0 post
areu 0 0 post
doin 0 0 post
我需要10个,所以我复制了9次
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
等等
现在我想用递增的值来更改星号10和0,如下所示:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_9 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_8 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_7 {
background: url(stars.png) no-repeat 0 -54px;
}
what 0 0 post
areu 0 0 post
doin 0 0 post
等等
那么我如何搜索/替换每个实例,进行计算并编写它呢?您可以使用带有
\=
符号的s/pattern/replace
构造来计算函数或表达式,如图所示:
递减.star\u 10
:
let g:decr = 11
fu! Decr()
let g:decr = g:decr - 1
return g:decr
endfu
:%s/.star_10/\=".star_" . Decr()/
同样,你也会这样做
let g:decr_18 = 18
fu! Decr18()
let g:decr_18 = g:decr_18 - 18
return g:decr_18
endfu
然后替换0代码>带有
:%s/no-repeat 0 0;/\="no-repeat 0 " . Decr18() . "px"/
对于这两个函数,都会声明一个(全局)变量,该变量在函数内进行操作并返回。对与模式匹配的每一行调用functin本身。模式被替换为\=
后面的表达式。您可能会为此编写一个函数,但我通常会做一些更简单的事情。我使用涉及^a和^X键的键宏(递增和递减数字)。使用qa
开始录音,使用带有计数修饰符的按键(例如18^X
),然后说10@就可以了 您可以使用宏轻松完成此操作。假设您只有以下内容:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
将光标放在第一个点上(在.star10
)并在正常模式下键入以下内容:
qa3yy3jp^Xjt;18^Xk0q
解释:
qa
将在寄存器“a”中启动宏记录
3yy
将拖动(复制)以下3行
3j
将光标向下放置3行
p
将粘贴过去拖动的文本
^X
(ctrl+X)将减少星级编号
j
将光标向下一行
t
将光标放在下一个之前代码>在当前行中
18^X
将使回传的y坐标减少18李>
k
将光标向上移动一行
0
将光标置于行的最下方
q
将完成宏录制
在那之后,你可能会有这样的事情
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_9 {
background: url(stars.png) no-repeat 0 -18;
}
就这样。只需将光标放在.star_9上的点上,然后按8@a
执行寄存器a中记录的宏八次。我需要这个解决方案,但也需要前导零支持。我对原始问题的使用更像示例1,而不是示例2(这是原始示例)
我创建了一个名为SearchIncr()的函数(搜索、替换和增量)
有四个必需的参数:target\u string
,replacement\u string
,start\u value
,increment\u value
。
还有两个可选参数:前导零
,位置
前导零
为正整数值,位置
为“之前”或“之后”。参见示例2
例1
然后您将获得:
what new00000001 post
areu new00000006 post
doin new00000011 post
.star_10 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -54px;
}
例2
然后您将获得:
what new00000001 post
areu new00000006 post
doin new00000011 post
.star_10 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -54px;
}
vimscript在这里:
" place functions here
function! SearchIncr(a1,a2,a3,a4,...)
" patn, repl, start, increment
let target = a:a1
let repl = a:a2
let startval = a:a3
let increment = a:a4
" 1st optional argument handles leading zeros
" process optional leading zero
if a:0 >= 1
let leadingz = a:1
else
" default to 0
let leadingz = 0
endif
" 2nd optional argument handles if target string goes before or after
" default is before
if a:0 == 2
" ideally set to 'after'
let repl_pos = a:2
else
let repl_pos = 'before'
endif
" inits
let l:incr = startval - increment
let lnum = a:firstline
" cycle though selection
while lnum <= a:lastline
" the FORMATTING string
if repl_pos == 'before'
let l:incrstring = '\=printf(''%s%0'. leadingz . 'd'',repl,l:incr)'
elseif repl_pos == 'after'
let l:incrstring = '\=printf(''%0'. leadingz . 'd%s'',l:incr,repl)'
else
"default to no leading zero and before placement
let l:incrstring = '\=printf(''%s%0d'',repl,l:incr)'
endif
" only increment counter when target matches
if match(getline(lnum),target) > 0
let l:incr = l:incr + increment
endif
" the search and replace
call setline(lnum,substitute(getline(lnum),target,
\ l:incrstring,'g'))
let lnum = lnum + 1
endwhile
endfunction
“将函数放在此处
函数!搜索增量(a1、a2、a3、a4等)
“patn,repl,start,increment
让目标=a:a1
设repl=a:a2
设startval=a:a3
设增量=a:a4
“第一个可选参数处理前导零
“进程可选前导零
如果a:0>=1
让导线Z=a:1
其他的
“默认为0
设导程z=0
恩迪夫
“第二个可选参数处理目标字符串是否在前面或后面
“违约发生在
如果a:0==2
“理想情况下设置为“之后”
让repl_pos=a:2
其他的
让repl_pos='before'
恩迪夫
“inits
设l:incr=startval-增量
设lnum=a:firstline
“循环选择
lnum仅使用纯vim资源,无需脚本:
:let c=10 | g/_\zs\d\+\ze/ s//\=c/ | let c-=1
:let c=0 | g/no-repeat 0 \zs\d\+/ s//\=c/ | let c-=18
这是一个很好的开始@Node17,哦,我用这个技巧在一个文件中重新编号6000帧。。。工作非常出色。关于@rene nyffenegger的答案:有没有一种方法可以将参数(start_value,decrement_value)放入函数中?虽然很多人都在谈论函数、插件等,但宏是vim的真正力量。vim为什么会用最“高级”的语言来扫地的另一个极好的例子IDE对这个答案感到非常高兴——这是我第一次真正了解Vim宏。这对于这个CSS片段来说非常具体,但我认为它可以通过一些工作适应其他事情。这个答案与OPs数据非常相关,他在OPs数据中反复使用相同的数字。我会问一个标题文字相同的问题,可能会以重复的方式结束,但我的数据在每一场比赛中都有不同的数字,只是模式相同。很难猜测用什么来代替^x
有没有一种方法可以在函数中放置参数(开始、递减值)?