Question

I swear I have looked and looked and looked. If I've missed the answer to this somewhere, I apologize; it means my search-fu failed me, not that I haven't tried.

I'm relatively new to bash scripts (:sigh: newbie), but I'm trying to write one that takes some input from the user and uses it in another command. My problem is that the other command needs to have any special characters in the user input escaped.

The basic form of the code is as follows:

#!/bin/bash

echo "Enter info:"
read _INFO

othercommand info=$_INFO 

Between the read and othercommand lines, I need to massage _INFO so that any special characters - spaces, single and double quotes ... pretty much any non-alphanumeric character, really - are escaped. For instance, an input of this pipe: | is my info! should become this\ pipe\:\ \|\ is\ my\ info\!

Note: I cannot put quotation marks - single or double - into the othercommand line, as it causes the command to fail. The info string needs to go as is, except escaped.

I've tried using the string substitution macro in various ways (here are some examples that only check for spaces):

_INFO = ${$_INFO// /\ }
_INFO = ${$_INFO// /\\ }
_INFO = ${$_INFO//" "/"\ "}
_INFO = ${$_INFO//" "/"\\ "}
_INFO = ${$_INFO//' '/'\ '}
_INFO = ${$_INFO//' '/'\\ '}

but I keep getting "bad substitution" errors.

So, not only is this too specific (only handles spaces) but it doesn't work anyway. How do I do this?

If I have to use sed or awk or something else not native to bash script-handling, I'd prefer to be given the exact line I'd need to use, as I'm entirely unfamiliar with them. (:sigh: newbie)

Was it helpful?

Solution

You can try printf for that:

printf -v _INFO '%q' "$_INFO"

OTHER TIPS

I think this is the proper form for that:

_INFO=${_INFO// /\ }
_INFO=${_INFO// /\\ }
_INFO=${_INFO//" "/"\ "}
_INFO=${_INFO//" "/"\\ "}
_INFO=${_INFO//' '/'\ '}
_INFO=${_INFO//' '/'\\ '}

When using parameter substitution form ${parameter/pattern/string}, you shouldn't add $ before your parameter inside {}.

See more about parameter expansion here: http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

Correct way is:

_INFO=${_INFO//[^a-zA-Z]/}

There is only one way to filter user input: use a whitelist. Blacklisting is never going to work because you can't guess all of the characters that can come into mind of the user, especially in unicode. So if you want to be safe then use a list of allowed characters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top