Probably the most effective way to do this - as I consider it - is with eval
. If you want literal values out of a shell expansion then the most straightforward way to get them is out of literal input - and the only way to get that out of a shell's output is to feed it right back in.
It is usually easiest to work with '
hard-quotes. The simple quote rule for a '
hard-quoted'
string is that it cannot contain a hard-quote - the only way to get one interpreted in such a context is to concatenate 2 or more quoted strings together like...
VAR='string'\''more string'
In that way the first quoted string ends at the second quote, the second quoted string is only a single backslash-escaped hard-quote, and third is the fourth hard-quote through the end.
And so what I might do if were you is...
eval "lol='$(nl='\
'; printf %s\\n "$lol" |
sed "s/Dot/&$nl/g
s/'"'/&\\&&/g
$s/$/'"'/
")"
In that way the same trailing newline which printf
adds to the var's value is the one that the command substitution strips - which is also the last character in output because the second-to last character is always a hard-quote - and that safely delimits the eval
statement because sed
escapes any hard-quotes which may appear in its input and there is one at the head of the string.
In truth, though, using command substitutions like that is often not a good practice anyway - and perhaps that is why it doesn't fit quite right all of the time. It is generally more effective to gather all output from a process for each of its process loops and pass it off at once on a single stream to another filter process in a pipeline than it is to nickle-and-dime the filters in that way.
And unless you have huge values in your shell variables - which is also usually a bad idea - something like this is probably a better way to go:
set -- "$lol"
while case "$1" in (*Dot*)
set -- "${1%Dot*}" "${1##*Dot}Dot
$2";;(*) ! lol=$1$2;; esac
do :; done