Unix: How to plan your escape

Knowing how and when to use the escape character can make your day, but commands get a little hairy when you first have to escape your escape.

Some Unix commands were made to help us break text on arbitrary boundaries so that we can process it in chunks while others give us a way to replace certain characters with others to make it easier for us to manipulate strings. Decades after learning the basics of awk, sed and tr, I still get a kick out of how handily these commands allow me to work with nearly any kind of text. But the game gets a little tricky when the character we want to work around happens to be a backslash. Let's look at why and how to get around backslash complications.

The need for escape

First, let's review some reasons why we have an escape character to begin with. It's easy enough to create a file called "myfile?" (at least it is if you don't already have files named "myfileX" where X is some other character), but removing such a file and not files named myfile2, "myfile3" might be a bit tricky. the shell, after all, gives special meaning to a ?. It takes a command such a rm myfile? as meaning to remove any file with a name that starts with "myfile" and has one additional character in its name.

$ touch myfile?
$ touch myfile2
$ ls
myfile?   myfile2

So, we can go ahead and have the remove command (assuming rm is aliased to rm -i) ask us which of the files we want to remove:

$ rm myfile?
rm: remove regular empty file `myfile?'? y
rm: remove regular empty file `myfile2'? n

Alternately, we can use the escape character -- the backslash -- to ignore the special meaning of the ? character and remove just myfile?:

$ rm myfile\?
rm: remove regular empty file `myfile?'? y

The commands touch myfile? and touch myfile\? do the same thing -- unless, of course, you have other files named myfileX (where X is any character). If that's the case, the touch myfile\? command will still create a file while touch myfile? will update the time stamp for all of your existing myfileX files. So, what if the file you want to work with has a backslash in its name? You can escape the backslash by using it twice. If you want a file named myfile\ for some bizarre reason, you can issue a touch myfile\\ command.

Escaping the escape

So, now let's look at what happens when you need to work around backslashes in your file names or data. One way to deal with backslashes is to use awk's gsub command to turn them into something less touchy. While this command works, however:


echo "one\two/three" | awk '{gsub("/","_"); print}'

this one gives us some grief:


echo "one\two/three" | awk '{gsub("\","_"); print}'

The particular flavor of grief is an "unterminated string" error.

awk: {gsub("\","_"); print}
awk:            ^ unterminated string

Why are we running into this? Because the backslash is invoking its escape character role and is making the shell ignore the special meaning of the second double quote (") character. Oops! So, let's try it this way instead:


echo "one\two/three" | awk '{gsub("\\","_"); print}'

$ ./bs2underline one\two/three No "unterminated string" error, but this isn't what we wanted. How about this way?


echo "one\two/three" | awk '{ gsub(/\\/,"_"); print }'

$ ./bs2underline one_two/three That works! Then, if we want just one part of the name, we can tell awk that we want to use the slash as our field separator and to print just one of the three fields. And let's change the backslash to a forward slash this time:


echo "one\two/three" | awk -F/ '{ gsub(/\\/,"/"); print $2 }'

In this script, gsub will change one\two/three to one/two/three and then the print command will print just the second of the /-separated strings:

$ ./bs2fs

Knowing how and when to use the \ character and how to get it do just what you want can be tricky, but can be made to work!

Read more of Sandra Henry-Stocker's Unix as a Second Language blog and follow the latest IT news at ITworld, Twitter and Facebook.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Now read: Getting grounded in IoT