LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash scripting general questions about quotation marks (https://www.linuxquestions.org/questions/linux-newbie-8/bash-scripting-general-questions-about-quotation-marks-909026/)

veeruk101 10-19-2011 02:20 PM

Bash scripting general questions about quotation marks
 
I've been learning about bash scripting and have been reading about the different ways that quotation marks affect variable 'expansion' and things like that, but it's a little confusing for me so I decided to look through some scripts and ask specific questions about them.

Sometimes I see an echo printed as follows:
Quote:

echo $"Usage: $0 {halt|reboot|shutdown}"
Just wondering why is it not the following?
Quote:

echo Usage: $0 {halt|reboot|shutdown}
This command actually caused my laptop to reboot on me! And I'm not sure exactly why from a bash point of view.


My next question is in the above statements, because it is an error situation, often followed by 'exit 1', why is the output not redirected to stderr? Meaning why isn't it the following:
Quote:

echo $"Usage: $0 {halt|reboot|shutdown}" 1>&2

Finally, in bash scripts why is it 'case "$1" in' rather than 'case $1 in'?

Thanks.

hapihakr 10-19-2011 09:45 PM

echo Usage: $0 {halt|reboot|shutdown}

This caused your machine to reboot, because the | is a command line operator that the output of the previous command should be fed as input for the next command. Thus the shell interpreted the above command as:

command 1: echo Usage: $0 {halt
the output of which is piped to
command 2: reboot
the output of which never gets piped to
command 3: shutdown}
because the machine rebooted with the 2nd command

The quotes are necessary to prevent the shell from interpreting the pipe operators (|).

echo $"Usage: $0 {halt|reboot|shutdown}" 1>&2

This would be a valid command and maybe in some circumstances desirable; however, standard error often is routed to a log file and since this is a usage message clearly intended for the user, then it should go to standard output, not standard error.

Hope I got all this right and I hope it clarifies things for you.

Good luck.

hapihakr 10-19-2011 09:58 PM

...why is it 'case "$1" in' rather than 'case $1 in'?

Again, the quotes prevent unintended consequences, when expanding the variable. Imagine if a user called the command with:

COMMAND |reboot

Then 'case "$1" in' would become 'case |reboot in' and your machine would reboot. Or...

COMMAND |bash

would give the user a shell with the same privileges as the running script.

It is good practice to quote your variable expansions and always look for unintended consequences.

hapihakr 10-19-2011 10:06 PM

Hmmmmm... on second thought, my last example was not well thought out... it wouldn't actually happen that way and the user would already have access to the shell, but it illustrates the principle: variable expansion can have unintended consequences and you should use quotes. Sorry if I caused any confusion.

grail 10-19-2011 11:21 PM

I think the explanations above are clear enough so this link may also shed some light for you.

SecretCode 10-20-2011 03:23 AM

I had not taken note of the $"..." usage before - I was expecting just
Code:

echo "Usage: $0 {halt|reboot|shutdown}"
Turns out that $"..." invokes localisation support, i.e. translation into local languages, and therefore a good thing for a program that's going to be distributed.
Code:

echo $"Usage: $0 {halt|reboot|shutdown}"
More here

Interesting!

David the H. 10-20-2011 12:37 PM

Quote:

Originally Posted by hapihakr (Post 4503057)
...why is it 'case "$1" in' rather than 'case $1 in'?

Again, the quotes prevent unintended consequences, when expanding the variable. Imagine if a user called the command with:

COMMAND |reboot

Then 'case "$1" in' would become 'case |reboot in' and your machine would reboot.

You're certainly right about unintended consequences as a general principle, but you aren't quite correct in this specific situation.

In general, once a character is inside a variable it loses it's special meaning. It's only when the string is re-expanded, and again interpreted by the shell, that it becomes special again. How it's interpreted depends on the context it's used in, however, and some shell built-ins in particular have their own processing rules.

In the case of the case keyword, the contents of the variable aren't interpreted as commands, so any shell-reserved characters such as pipes inside them remain safe. Even whitespace is ok, since word-breaking doesn't occur either. case only views the contents as a literal string to match against.

So case $1 in and case "$1" in are exactly the same syntax-wise. The quotes don't help, but they don't hurt either. When in doubt, always quote.

Understanding how quotes work is vital, and I applaud the OP for taking the time to study it. If he hasn't seen these links before, I recommend them now (in addition to the "quotes" link given above):

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting

BTW, the [[..]] test keyword is another place where quoting isn't necessary, at least for the left side of the equation. They can be important on the right side if you're doing globbing or regex matches.

http://mywiki.wooledge.org/BashFAQ/031


All times are GMT -5. The time now is 09:02 PM.