LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash - escape all special characters in variable string? (https://www.linuxquestions.org/questions/linux-newbie-8/bash-escape-all-special-characters-in-variable-string-924812/)

arashi256 01-20-2012 10:16 AM

Bash - escape all special characters in variable string?
 
I have the following script (test.sh):

Code:

#!/bin/bash
INPUT=$1
printf "%s\n" "LINE: ${INPUT}"

If I then do: -

./test.sh *

It produces: -

Code:

LINE: test.sh
Not "LINE: *" like I want. Now, in what I want to write, $INPUT could have many special characters in it - how do I escape them all?

I've tried: -

printf "%q\n" "LINE: ${INPUT}"

and

printf "%b\n" "LINE: ${INPUT}"

None of which work. I just want it to print any special characters within the variable $INPUT as a String. Can it be done?

Ser Olmy 01-20-2012 11:46 AM

The problem isn't the script, it's shell expansion at work. The shell expands the asterisk to all file names in the current directory before passing it to the script.

Try:

./test \*

grail 01-20-2012 11:53 AM

Or try surrounding the input in single quotes so the shell does not interpret any special characters

devUnix 01-20-2012 12:55 PM

Try this:

PHP Code:

[demo@devhost ~]$ read rubbish
star is also called dash _ / \ = + & ^ % $ # wow!


[demo@devhost ~]$ echo "'$rubbish'"
'* star - is also called dash _ /  = + & ^ % $ # wow!'
[demo@devhost ~]$ 

or:

[
demo@devhost ~]$ echo "$rubbish"
star is also called dash _ /  = + & ^ % $ # wow!
[demo@devhost ~]$ 


arashi256 01-21-2012 02:32 PM

Hi,

I realise that I could do

Code:

./test.sh \*
...but this only works on...well....this example. $1 could have any number of *'s in it (which is actually what I have - the above was to show the problem), so I need to be able to escape the shell expansion from within the script. I obviously can't do: -

Code:

INPUT='$1'
as $INPUT will be literally '$1' rather than '*'. I tried using sed, but I've hardly used it before and couldn't get it to escape every '*' in $1. Little help?

Thank you for the theory as to why I'm getting the contents of the directory though - I didn't know about shell expansion :)

David the H. 01-22-2012 03:51 AM

Quote:

Originally Posted by arashi256 (Post 4580875)
... so I need to be able to escape the shell expansion from within the script.

No, you can't do it inside the script at all. The problem is that the running shell is expanding the globs before the script is even run. When you run:

Code:

./test.sh *
...the shell first parses the line, replaces the "*" with a list of files that match the glob, and then executes the script. So the command that's actually being run is the script name plus all the files in the directory as arguments. Like this:

Code:

./test.sh file1 file2 file3 file4 etc...
You'd only get a literal "*" is if the directory is empty and nothing is matched.


The only way you can pass a raw globbing value is to escape or quote the arguments that you want to pass to the shell on the command line, or to disable globbing in the parent shell.

This is true of all shell syntax. If there's anything that's considered important by the shell on the line, it will be parsed and replaced before the command is run, unless it's protected by quotes or backslash escapes.


Edit: BTW, once a value is stored in a variable or parameter, all the characters in the string are literal, and they will be treated as such by the script as long as you properly quote it. Only unquoted parameters are ever parsed for shell-reserved characters (unless you use a specific command option like printf's "%b" or echo's "-e" to force it to interpret them).

So your only real problem is with the initial setting of "$1", and how you quote it afterwards. How about showing us exactly what you need to do, rather than fooling around with an example that may not reflect your actual purpose?

devUnix 01-22-2012 01:02 PM

Hi!


I gave you the working example above but you do not seem to check it out. Here is a script, if scrip is the only way to make you understand, that does what you expect regarding Shell Expansion:

Code:

[demo@devhost Bash]$ cat rubbish.sh
#!/bin/bash
PARA=$1
echo "You Passed: "
echo "$PARA"
exit 0

[demo@devhost Bash]$ ./rubbish.sh '! @ # * wow stars ***'
You Passed:
! @ # * wow stars ***

You must Single-Quote 'parameters' at the Shell/Command prompt. Then it will work fine.

If you think each character/word is to be taken as a separate parameter inside your script then you can simply split the line (PARA=$1) to work with them. That is your homework to learn more.

arashi256 01-23-2012 03:39 AM

Ah, sorry - misread. Many thanks, that fixed it. No need to be quite so snide about it, tho :)

arashi256 01-23-2012 09:04 AM

Okay, since I'm also doing: -

Code:

echo $LINE >> SOME_FILE.tmp # won't work
where line has asterisks in it, you can disable bash shell expansion within your script like so...

Code:

set -f
echo $LINE >> SOME_FILE.tmp # will work
set +f

...in case anyone else has a similar problem.

catkin 01-23-2012 09:40 AM

Or you could put double quotes around $LINE

arashi256 01-23-2012 09:43 AM

Quote:

Originally Posted by catkin (Post 4582173)
Or you could put double quotes around $LINE

Yeah, I suppose that would be better :D


All times are GMT -5. The time now is 03:08 AM.