Patrick Li Patrick Li - 22 days ago 7
R Question

Insert a character at a specific location in a string

I would like to insert an extra character (or a new string) at a specific location in a string. For example, I want to insert

d
at the fourth location in
abcefg
to get
abcdefg
.

Now I am using:

old <- "abcefg"
n <- 4
paste(substr(old, 1, n-1), "d", substr(old, n, nchar(old)), sep = "")


I could write a one-line simple function for this task, but I am just curious if there is an existing function for that.

Answer Source

You can do this with regular expressions and gsub.

gsub('^([a-z]{3})([a-z]+)$', '\\1d\\2', old)
# [1] "abcdefg"

If you want to do this dynamically, you can create the expressions using paste:

letter <- 'd'
lhs <- paste0('^([a-z]{', n-1, '})([a-z]+)$')
rhs <- paste0('\\1', letter, '\\2')
gsub(lhs, rhs, old)
# [1] "abcdefg"

as per DWin's comment,you may want this to be more general.

gsub('^(.{3})(.*)$', '\\1d\\2', old)

This way any three characters will match rather than only lower case. DWin also suggests using sub instead of gsub. This way you don't have to worry about the ^ as much since sub will only match the first instance. But I like to be explicit in regular expressions and only move to more general ones as I understand them and find a need for more generality.


as Greg Snow noted, you can use another form of regular expression that looks behind matches:

sub( '(?<=.{3})', 'd', old, perl=TRUE )

and could also build my dynamic gsub above using sprintf rather than paste0:

lhs <- sprintf('^([a-z]{%d})([a-z]+)$', n-1) 

or for his sub regular expression:

lhs <- sprintf('(?<=.{%d})',n-1)