I want to change 3rd byte of a string to x, i'm currently using this code:

let s = s[:1] . 'x' . s[3:]

It's a bit awkward, i wish i can do let s[2] = 'x', but that's not allowed.

Are there any other built-in ways to do it nicely?


In vimscript, strings are invariant: it would be very hard to poke odd bytes into a series of Unicode characters without trashing the entire thing.

Concatenation of parts as you have done is not so hard!

An alternative approach uses the substitute() function:

let s = substitute(s, "^\\(..\\).", "\\1x", "")

but that is not much more readable or flexible. It is possible to wrap up both attacks in a more useable fashion:

function! s:replacechar(src, pos, chr)
  if len(a:src) < a:pos
    return a:src
        return (a:pos ? a:src[0:(a:pos-1)] : "") . a:chr . a:src[(a:pos+1):]

function! s:rereplacechar(src, pos, chr)
  let l:pat = "^\\(" . repeat(".", a:pos) . "\\).\\(.*\\)"
  let l:rep = "\\1" . a:chr . "\\2"
  return substitute(a:src, l:pat, l:rep, "")

(Edit to correct a:p == 0 bug spotted by Mass)

Hope that helps


| improve this answer | |
  • bug: when a:pos = 0, a:pos-1 is -1 and a:src[0:-1] yields the whole string. – Mass Apr 27 '19 at 14:04
  • @TimFerguson Thanks. But i only want to know other built-in ways to do this, function is not an option. No need to consider unicode, it's byte index, not character index. You code would be clearer if you use single quote string. – dedowsdi May 6 '19 at 3:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.