13

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?

Arafat Hasan
  • 2,811
  • 3
  • 21
  • 38

4 Answers4

19

it works like python:

echo '0123456'[2:4]
234

For detailed doc:

:h expr-[:]
Kent
  • 189,393
  • 32
  • 233
  • 301
5

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
Luc Hermitte
  • 31,979
  • 7
  • 69
  • 83
5

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-[:].

Arminius
  • 2,363
  • 1
  • 18
  • 22
2

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.

Uprooted
  • 941
  • 8
  • 21