James Haigh
James Haigh

Reputation: 1272

How does one ‘contract’ strings to escape special characters in Bash?

There are many ways to expand an escaped string, but how can a shell command be made to take a string as an argument and escape it?

Here are some examples of different ways of expansion:

$ echo -e '\x27\\012\b34\n56\\\aa7\t8\r 9\0\0134\047'
'\0134
 9\'7   8
$ echo $'\x27\\012\b34\n56\\\aa7\t8\r 9\0\0134\047'
'\0134
 9\a7   8
$ PS1='(5)$ '  # At least tab-width - 3 long; 5 columns given typical tab-width.
(5)$ printf %b '\x27\\012\b34\n56\\\aa7\t8\r 9\0\0134\047'
'\0134
 9\'(5)$ 

Note: there's actually a tab character between the 7 and 8 above, but the markup rendering seems to break it.

Yes, all sorts of craziness in there. ;-)

Anyway, I'm looking for the reverse of such escape expansion commands. If the command was called escape, it would satisfy these properties:

$ echo -ne "$(escape "$originalString")"

Should output the verbatim value of originalString as would ‘echo -n "$originalString"’. I.e. it should be an identity.

Likewise:

$ escape "$(echo -ne "$escapedString")"

Should output the string escaped again, though not necessarily in the same way as before. E.g. \0134 may become \\ or vice versa.

Upvotes: 2

Views: 492

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295373

Don't use echo -e -- it's very poorly specified in POSIX, and considered deprecated for all but the simplest uses. Bash has extensions to its printf that provide a better-supported approach:

printf -v escaped_string %q "$raw_string"

...gives you a shell-escaped string from a raw one (storing it in a variable named escaped_string), and

printf -v raw_string %b "$escaped_string"

...gives you a raw string from a backslash-escaped one, storing it in raw_string.


Note that the two escape syntaxes are not equivalent -- strings escaped with printf %q are ready for eval, rather than for printf %b.

That is, you can safely run:

eval "myvar=$escaped_string"

...when escaped_string has been created with printf %q as above.


That said: What's the use case? It's strongly preferred to handle raw strings as raw strings (using NUL terminaters when delimiting is necessary), rather than converting them to and from an escaped form.

Upvotes: 6

Related Questions