4

I'm looking for a one liner to replace any character in a variable string at a variable position with a variable substitute. I came up with this working solution:

echo "$string" | sed "s/./${replacement}/${position}"

An example usage:

string=aaaaa
replacement=b
position=3
echo "$string" | sed "s/./${replacement}/${position}"
aabaa

Unfortunately, when I run shellcheck with a script which contains my current solution it tells me:

SC2001: See if you can use ${variable//search/replace} instead.

I'd like to use parameter expansion like it's suggesting instead of piping to sed, but I'm unclear as to the proper formatting when using a position variable. The official documentation doesn't seem to discuss positioning within strings at all.

Is this possible?

Alex Jansen
  • 1,455
  • 5
  • 18
  • 34
  • The "working solution" doesn't work in general. Test with `replacement='&'` and `replacement=/`. See [Escape a string for a sed replace pattern](https://stackoverflow.com/q/407523/4154375). – pjh Feb 14 '19 at 19:57
  • @pjh, yes -- I was very explicit in comment discussion (now removed apparently) preceding the answer that it was not in any way a general-case solution; the OP indicated that it was adequate for their use case, and requested that the commented suggestion be posted as an answer. – Charles Duffy Feb 14 '19 at 20:11

1 Answers1

5

Bash doesn't have a general-case replacement for all sed facilities (the shellcheck wiki page for warning SC2001 acknowledges as much), but in some specific scenarios -- including the case posed -- parameter expansions can be combined to achieve the desired effect:

string=aaaaa
replacement=b
position=3
echo "${string:0:$(( position - 1 ))}${replacement}${string:position}"

Here, we're splitting the value up into substrings: ${string:0:$(( position - 1 ))} is the text preceding the content to be replaced, and ${string:position} is the text following that point.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • The expression for the new string is correct, but it can be simplified to `${string:0:position-1}${replacement}${string:position}`. – pjh Feb 14 '19 at 20:06
  • It's not relevant to the substance of the question, but the `echo` command doesn't work in general. Test with `string=nn ; replacement=- ; position=1`. – pjh Feb 14 '19 at 20:10