2
#!/bin/bash
wineuser=tom
su $wineuser -c "sed -i '$ialias ptgui "wine ~/.wine/drive_c/Program\ Files/PTGui/PTGui.exe\"' /usr/people/$wineuser/config/cshrc.csh"

The acutal line inserted to tom's cshrc.csh should look like

alias ptgui 'wine ~/.wine/drive_c/Program\ Files/PTGui/PTGui.exe'

the sed command '$ialias...' $i is inserting before the last line in the file, it is not a defined variable.

Tips or manuals explaining multi-level escapes also welcome.

1 Answer 1

4

The Theory

The rules are :

  • inside a ' delimited string, nothing gets interpreted and anything but a ' doesn't have special meaning. This means that only a ' need escaping but it also mean that, in order to escape it, you need the '\'' construct. (The first ' ends the string, the following \' adds a literal ' (the escape prevents the start of a new string) and the last ' start a new string. since those three strings are not separated by a delimiter (usually a space), they will be seen as a single continuous string.

  • Inside a " string, variable expansion occurs and escapes are interpreted. Therefore, if you want a literal \, you will need to escape it. Also, if you want a literal $, you also need to escape it (else it will be interpreted as variable expansion).

You can escape your command differently by combining those two quoting style as you want. One possible solution for your specific question is listed below.

Also, keep in mind that sed also interprets \ as an escape character, meaning you also need to escape that character when using it literally inside a sed script.

Example

Personally, I find it easier to start by the inner most code unit and work my way outwards, quoting each time in the inner code unit the special characters for the outer quoting method used.

For example, if you wanted to replace the string It's a test by It's my test in the file /home/user/I have spaces in my name.txt and put the result in the file /home/user/NoSpaces.txt, you could use " quoting around it to make it easier, like so :

sed "s/It's a test/It's my test/" "/home/user/I have spaces in my name.txt" >/home/user/NoSpaces.txt

Now, if you wanted to store this inside a variable, you would have to add another quoting level.

  • You could do it using ' (which mean only having to escape other ' characters in your current string):

    myvar='sed "s/It'\''s a test/It'\''s my test/" "/home/user/I have spaces in my name.txt" >/home/user/NoSpaces.txt'
    
  • You could also do it using by using " style quotes:

    myvar="sed \"s/It's a test/It's my test/\" \"/home/user/I have spaces in my name.txt\" >/home/user/NoSpaces.txt"
    

The rule of thumb is to always go with the solution that looks the cleanest to you.

A solution

That being said, for your specific problem, you could try this :

cmd="sed -i '\$ialias ptgui '\\''wine ~/.wine/drive_c/Program\\\\ Files/PTGui/PTGui.exe'\\' /usr/people/$wineuser/config/cshrc.csh"
su "$wineuser" -c "$cmd"

Note that I would suggest to use append instead of insert command for sed, but that is outside the scope of the question.

2
  • Perfect, thank you! It appears that each escape level requires another backslash? I didn't know that
    – Party Time
    May 20, 2015 at 21:33
  • @PartyTime Well, it's not that simple. I edited my answer to reflect that. Basically, for each level, you need to escape the right characters depending on which quoting style you use for the next outer level.
    – user43791
    May 20, 2015 at 21:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .