Vim search replace regex + incremental function

不羁的心 提交于 2020-01-14 03:35:14

问题


I'm currently stuck in vim trying to find a search/replace oneliner to replace a number with another + increment for each new iteration = when it finds a new match.

I'm working in xml svg code to batch process files Inkscape cannot process the text (plain svg multiline text bug).

<tspan
       x="938.91315"
       y="783.20563"
       id="tspan13017"
       style="font-weight:bold">Text1:</tspan><tspan
       x="938.91315"
       y="833.20563"
       id="tspan13019">Text2</tspan><tspan
       x="938.91315"
       y="883.20563"
       id="tspan13021">✗Text3</tspan>

etc.

So what I want to do is to change that to this result:

<tspan
       x="938.91315"
       y="200"
       id="tspan13017"
       style="font-weight:bold">Text1:</tspan><tspan
       x="938.91315"
       y="240"
       id="tspan13019">Text2</tspan><tspan
       x="938.91315"
       y="280"
       id="tspan13021">✗Text3</tspan>

etc.

So I duckducked and found the best vim tips resource from zzapper, but I cannot understand it:

convert yy to 10,11,12 :

:let i=10 | ’a,’bg/Abc/s/yy/\=i/ |let i=i+1

I then adapted it to something I can understand and should work in my home vim:

:let i=300 | 327,$ smagic ! y=\"[0-9]\+.[0-9]\+\" ! \=i ! g | let i=i+50

But somehow it doesn't loop, all I get is that:

<tspan
       x="938.91315"
       300
       id="tspan13017"
       style="font-weight:bold">Text1:</tspan><tspan
       x="938.91315"
       300
       id="tspan13019">Text2</tspan><tspan
       x="938.91315"
       300
       id="tspan13021">✗Text3</tspan>

So here I'm seriously stuck. I cannot figure out what doesn't work :

  • My adaptation of the original formula ?
  • My data layout ?
  • My .vimrc ?

I'll try to find other resources by myself, but on that kind of trick they are pretty rare I find, and like in zzapper tips, not always delivered with a manual.


回答1:


One way to fix it:

:let i = 300 | g/\m\<y=/ s/\my="\zs\d\+.\d\+\ze"/\=i/ | let i += 50

Translation:

  • let i = 300 - hopefully obvious
  • g/\m\<y=/ ... - for all lines matching \m\<y=, apply the following command; the "following command" is s/.../.../ | let ...; the regexp:
    • \m - "magic" regexp
    • \< - match only at word boundary
  • s/\my="\zs\d\+.\d\+\ze"/\=i/ - substitute; the regexp:
    • \m - "magic" regexp
    • \d\+ - one or more digits
    • \zs...\ze - replace only what is matched between these points
    • \=i - replace with the value of expression i
  • let i += 50 - hopefully obvious again.

For more information: :help :g, :help \zs, :help \ze, help s/\\=.




回答2:


Just to add my take as a memo (wrote this as an answer as an EDIT didn't seem right). Sorry it is not the best vim scripting here but it enables me to understand (I'm not a vim specialist).

:let i=300 | 323,$g/y="/smagic![0-9]\+.[0-9]\+!\=i!g | let i+=50

Assign the initial value to i :

:let i=300

Start :global (:g) function from line 323 to the end of file:

323,$g

Pattern to match for executing the commands (litteral text here)

y="

Substitution with magic on (magic meaning special characters "enabled")

smagic

Pattern to find

[0-9]\+.[0-9]\+

(numbers between 0-9 one or more times, a litteral dot, the numbers again)

Replaced with

\=i

\= tells vim to evaluate i not to write it litterally

Increment i with 50 for the next iteration

let i+=50

This part is still in the g function.

The separators, in bold: | are the separators between the different functions / are the separators in the :g function ! are the separators in the smagic function



来源:https://stackoverflow.com/questions/33317532/vim-search-replace-regex-incremental-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!