Is there any substr()
like function to get substring in vim script? If not what is the best replacement or alternative for this kind of task?

- 2,811
- 3
- 21
- 38
4 Answers
it works like python:
echo '0123456'[2:4]
234
For detailed doc:
:h expr-[:]

- 189,393
- 32
- 233
- 301
-
3Another access point to the same functionality is strpart strpart("myfoo", 2,3) => foo – Leonard Jun 09 '18 at 17:15
-
4In Python, `'0123456'[2:4]` returns `23`. – FMc Sep 29 '18 at 20:26
For multi-bytes characters, there is also :h strcharpart()
If the function does not exist in your old flavour of Vim, it could be emulated with for instance
function! lh#encoding#strpart(mb_string, p, l)
" call lh#assert#value(lh#encoding#strlen(a:mb_string)).is_ge(a:p+a:l)
return matchstr(a:mb_string, '.\{,'.a:l.'}', 0, a:p+1)
endfunction

- 31,979
- 7
- 69
- 83
The VimL expression mystring[a:b]
returns a substring from byte index a
up to (and including) b
.
But be aware that the semantics are different from Python's subscript notation or Javascript's str.slice()
. In particular, VimL counts the bytes instead of the characters for indexing, and the byte at the end of the range (the byte at index b
) is included.
These examples illustrate how the behavior differs:
VimL Python
--------------------------------
s = "abcdef"
s[0] a a
s[5] f f
s[0:1] ab a
s[2:4] cde cd
s[-1:] f f
s[:-1] abcdef abcde
s[-2:-1] ef e
s = "äöü"
s[0:2] ä\xc3 äö
Also, look up the documentation at :help subscript
and :help expr-[:]
.

- 2,363
- 1
- 18
- 22
Depends on whether you want byte range or character range. For byte range b
through e
its str[b:e]
, but for character range you'll need byteidx function:
str[byteidx(str,b):byteidx(str,e+1)-1]
For multibyte characters results differ.

- 941
- 8
- 21