4

In bash, you can use printf "%q" to escape the special characters in a string. I've added a line break in the following examples for clarity's sake:

$ printf "%q\n" "foo"
foo
$ printf "%q\n" 'foo$bar'
foo\$bar
$ printf "%q\n" "foo    bar"  # Tab entered with Ctrl+V Tab
$'foo\tbar'

You can supply the -v option to printf to stick the output into a variable, rather than echoing to stdout.

Now what if I want to echo the original, unescaped string back to stdout? If I just do a simple echo, it includes all the meta/control characters; echo -e gets me slightly further, but not to a fully unescaped state.

Xophmeister
  • 8,884
  • 4
  • 44
  • 87

1 Answers1

2

Use printf and eval to "unescape" the string (it is perfectly safe, since it is quoted by bash already). echo is, in general, dangerous with arbitrary user input.

eval printf '%s\\n' "$var"

The argument to printf is %s\\n with double backslashes even within the single quotes, since eval will take it as one argument and then strip it (evaluate it) as is, so it effectively becomes something like: printf %s\\n $'12\n34 56' which is a perfectly safe and valid command (the variable even includes a newline and space, as you can see).

NOTE: This assumes the input is escaped from printf '%q' or similar, otherwise it is not safe.

kktsuri
  • 333
  • 2
  • 11
  • This solution seems to be unsafe. `var='a b; ls'; eval printf '%s\\n' "$var"` revealed the contents of my working directory. – eivour Jan 12 '23 at 12:17
  • Well it obviously assumes the input is escaped from printf '%q', in that case it's not unsafe because ; cannot appear in the input, only \; (its escaped form). I edited to add this information. – kktsuri May 27 '23 at 19:57