Re: No escape from the dollar sign in SED

"Cameron Simpson [email protected] [sed-users]" <[email protected]> Wed, 4 Apr 2018 15:27:30 +1000
Newsgroups gmane.editors.sed.user
Message-ID <[email protected]>
On 04Apr2018 04:07, [email protected] <[email protected]> wrote:
>I was reading the excellent SED FAQ bud could not find an alternate solution 
>to the following:
>
>The script below replaces the literal string $path with the contents of variable $usb
>
>The only way I could get this to work under busybox ash is with completely bare \\$
>to escape the literal $path in two separate chunks as \\$'path' which is REALLY weird.
>
>root@zero:~# usb='/mnt/stick'; echo 'Path $path is it!' | sed -r 's|'\\$'path'"|$usb|g"
>Path /mnt/stick is it!
>
>It's great that it works because it allows me to pre-process my here-block before I
>write it out to a file, but jeepers it would be nice to understand what's happening
>and whether there are any other ways to do this under busybox with ash.
>
>Here is the slightly simplified here-doc version which I actually use:
>
>usb='/mnt/stick'
>cat <<-'EOF' | sed -r 's|'\\$"path|$usb|g"
>echo and here it is:
>ftpdir=$path
>echo more stuff
>EOF

Ok, first up I suspect busybox and ash are not special; they should cope with 
standard shell syntax. So my advice here is generic.

First a nit: what you've got there is a "redundant cat". You can just write 
this:

  sed -r 's|'\\$"path|$usb|g" <<'-EOF'
  echo and here it is:
  ftpdir=$path
  echo more stuff
  EOF

The other thing is that I would avoid shift quotes when possible. I'd be 
writing:

  sed -r "s|\\\$path|$usb|g" <<'-EOF'

First plan what sed needs to receive: what is sees _after_ the shell has done 
quote processing:

  s|\$path|/mnt/stick|g

So you objective is to get that in from the shell. You want $usb inserted, so 
naturally you want a double quoted string. Within double quote you need a 
literal backslash and a literal dollar for the \$path part, so both need 
escaping:

  s|\\\$path|$usb|g

Then put quotes around it and you're ready.

As a final remark, I often use ^G (control-G) as a sed delimiter, just because 
it isn't part of normal text.

Cheers,
Cameron Simpson <[email protected]>