1

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)

Wilson F
  • 1,250
  • 1
  • 20
  • 37

3 Answers3

2

You can try printf for that:

printf -v _INFO '%q' "$_INFO"
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
  • Bingo! That's exactly what I needed; it works perfectly. I'd seen some solutions with printf, but hadn't seen the "-v" parameter. Thank you very much! – Wilson F Sep 12 '13 at 20:34
1

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

konsolebox
  • 72,135
  • 12
  • 99
  • 105
0

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.

Aleks-Daniel Jakimenko-A.
  • 10,335
  • 3
  • 41
  • 39
  • That removes the offending characters, but it doesn't replace them with escaped equivalents. How do I do that? – Wilson F Sep 12 '13 at 19:50
  • @WilsonF What? how are you going to escape every unicode character? How are you going to escape this? ``‫‬‭‮‪‫‬‭‮``҉What about this? – Aleks-Daniel Jakimenko-A. Sep 12 '13 at 20:12
  • That's what I want to know. Is your question a rhetorical way of saying it can't be done? – Wilson F Sep 12 '13 at 20:23
  • @WilsonF even stackoverflow failed to [handle my previous comment correctly](https://dl.dropboxusercontent.com/u/71236259/2013-09-12-232403_659x51_scrot.png). There's no other way but removing them, UNLESS you really tell us what are you going to do with your data. Maybe you want to pass it to wget? – Aleks-Daniel Jakimenko-A. Sep 12 '13 at 20:25