Manipulation of strings in vim

Go To


In my opinion Vimscript has not a lot of features for manipulating strings.
I often use matchstr(), substitute() en less often strpart().
Maybe there's more than that.

What is p.e. the best way to remove all text between linenumbers in the next string "a"?

let a = "\%8l............\|\%11l..........\|\%17l.........\|\%20l...." --> etc 

I want to keep only the digits and put them in a list.
(the text between linenumbers can be diffent)

output I want to obtain:
['8', '11', '17', '20'] --> etc

2012-04-04 06:44
by Reman
Please give a sample of what you want to obtain - romainl 2012-04-04 07:24
'<,'>s/(\d+).*$/\1/g or describe what you need more precisel - kirilloid 2012-04-04 07:32
romainl, kirilloid, please see after edit - Reman 2012-04-04 07:46


You're looking for split()

echo split(a, '[^0-9]\+') 


Given the new constraint: only the numbers from \%d\+l, I'd do:

echo map(split(a, '|'), "matchstr(v:val, '^%\\zs\\d\\+\\zel')")

NB: your vim variable is incorrectly formatted, to use only one backslash, you'd need to write your string with single-quotes. With double-quotes, here you'd need two backslashes. So, with

let b = '\%8l............\|\%11l..........\|\%17l.........\|\%20l....'

it becomes

echo map(split(b, '\\|'), "matchstr(v:val, '^\\\\%\\zs\\d\\+\\zel')")
2012-04-04 08:50
by Luc Hermitte
This is nice Luc but it doesn't exactly what I want. It split up also if there is a digit in the text between %\d+l' - Reman 2012-04-05 07:00
Luc, What would be the split code if there is also >-< in string "b": \%8l.....\|\%>10l-\%<15l\.....\|\%17l.....? The result must be `['8','11-14','17'] Thanks in advance : - Reman 2012-04-14 12:53
sorry, the result must be ['8', '11', '12', '13', '14', '17']Reman 2012-04-14 13:05


One can take advantage of the substitute with an expression feature (see :help sub-replace-\=) to run over all of the target matches, appending them to a list.

:let l=[] | call substitute(a, '\\%\(\d\+\)l', '\=add(l,submatch(1))[1:0]', 'g')
2012-04-05 14:37
by ib.
Damn. We can always learn new vim tricks. I wasn't aware that substitute() supports \=. Thanks - Luc Hermitte 2012-04-06 08:17
Ib, do you know what would be your split code if there is also >-< in string "b": \%8l.....\|\%>10l-\%<15l.....\|\%17l.... ? The result must be ['8', '11-14', '17'] or even better ['8', '11', '12', '13', '14', '17']Reman 2012-04-15 08:10
I have created a function to fill block of lines with spaces and another to copy block of lines to clipboard. I select them first in another function. : - Reman 2012-04-15 19:06
@Remonn: It is enough to use \%>10l\%<15l to match a range of lines (number 9 through 14). For what purpose do you insert a hyphen between those atoms - ib. 2012-04-15 22:26
"@Ib, I found the solution trying, trying and trying :) Using your above regex with this regex does the job to put the "-" in the list as well :call substitute(s:zoek, '\\%[<>]*\(\d\+\)l\.*\\%[<>]*\(\d\+\)l\.*', '\=add(l,(submatch(1)+1)."-".(submatch(2)-1))[1:0]', 'g') :) --- Why I need the hyphen? I want to keep the ">" and "<" together in only one index - Reman 2012-04-16 10:44