Click to See Complete Forum and Search --> : [SOLVED] String comparison in while [ ... ]
# if user input is a 'y', repeat the process
a="y"
while [ $a=y ]
do
read a
echo "Bang! $a"
done
In the above script,
while [ $a=y ]
while [ $a="y" ]
while [ "$a"="y" ]
while [ $a='y' ]
etc., etc. all fails. I'm completely stuck.
What could be the correct syntax and why?
asarch
05-27-2007, 02:24 AM
Just one rule:
When you are comparing string put always the variable between ' or "
So, your expression might look at this:
while [ "$a"=="y" ]
or like this:
while [ '$a'=='y' ]
and even like this:
while [ "$a"=='y' ]
...
while [ '$a'=="y" ]
And always use '==' for comparing, you know, just for improving readability.
Good luck and happy hacking!!! :D
Thanks.
I thought $a should denote a string.
If "$a" is a string, then what $a could be???
asarch
05-27-2007, 01:02 PM
Anything else that is not a string:
set a = 1
while ($a <= 100)
if ($a < 10) then
...
else
...
endif
end
And "$a" is also useful for path names containing spaces
If you do this, you get an error message from mv:
set a = "~/The Beatles/Abbey Road/10 - Sun King.flac"
mv -v $a .
But if you surround $a with " or with ' it will works:
set a = "~/The Beatles/Abbey Road/10 - Sun King.flac"
mv -v "$a" .
or
set a = '~/The Beatles/Abbey Road/10 - Sun King.flac'
mv -v '$a' .
bwkaz
05-27-2007, 02:25 PM
set a = 1
while ($a <= 100)
if ($a < 10) then
...
else
...
endif
end
OK, why do you use csh? :p (At least, I'm assuming that's csh, because it isn't valid sh syntax.)
But if you surround $a with " or with ' it will works: Not if you use single quotes.
If you use single quotes, then sh (and sh-compatible shells, including bash) do not substitute the value of the variable. Inside single quotes, no characters have any kind of special meaning, including the dollar sign.
(I suspect hiwa's problem is related to the lack of spaces around the equals sign. Shells do word splitting on any command line that they get, and the comparison operators have to be separate words. Word splitting happens on spaces, tabs, and newlines by default (although newlines end the command). So you need a space or tab between the first argument to the equal comparison and the equal comparison itself.)
> hiwa's problem is related to the lack of
> spaces around the equals sign
Thanks. You are right. But another half of my problem was the confusion below:
shell variable:
a .... name == address
$a ... data content the name/address refers, i.e. the value of a.
"$a" ... string made from the data content
then, after a="love" assignment, "$a" should be string "love" and $a1 is simply, simply, simply, eh... what? In short, my confusion is, if we shoule write "$a" to get the string "love", then, WHAT IS $a after all? What we get by writing a simple $a ?
bwkaz
05-28-2007, 10:04 AM
(All of the following is a description of sh-compatible shells, i.e. sh, bash, ksh, and a few others. csh/tcsh/etc. follow completely different rules -- but then, I don't use them, either. ;))
But another half of my problem was the confusion below:
shell variable:
a .... name == address
$a ... data content the name/address refers, i.e. the value of a.
"$a" ... string made from the data content OK. :)
When you say this in the shell (or a script):
a the shell interprets it as a single word, a. (This could be a filename, or a command name, or an argument to a command, or whatever. Which one it is depends on where in the command it gets put, and how the command interprets it. But that doesn't really matter, either: the shell just uses a.)
When you say this in the shell:
a=fdsfsfa then the shell creates a new variable named a, and assigns the value fdsfsfa to it.
After you do that, you can do this:
$a and the shell will replace the $a part with its value (fdsfsfa).
You can also do this:
"$a" and the shell will replace the $a part with its value again (fdsfsfa). The difference here is that the shell does the variable replacement before doing quote interpretation, so you end up with an expression that looks like "fdsfsfa" (with the quotes still around it).
The only place this really matters is when your variable's value has spaces in it, or can be empty: then you have to put double quotes around the variable to keep it exactly one word after expansion.
(You can also do this:
'$a' and the shell will leave that as '$a'. It will later remove the single quotes, but on a single pass of evaluation, it won't substitute the value of the a variable.)
The above things are the only operations the shell will do with variables (i.e. names preceded by $ characters): it will only ever substitute a variable's value for its name. The shell does not care what "type" the variable's value has; it treats everything as a string. (So even if you had said a=006543, the shell would have substituted 006543 everywhere it saw $a, whether that was inside double quotes or on its own.)
The only standard program that I can think of that cares about "types" is test (which goes by several names: /bin/test and /bin/[ are two of them, plus there are the "test" or "[" shell builtin operations). Other programs may exist, but I don't think I've ever seen any. The test builtin or program has two different kinds of equality comparisons: string and numeric. You get string equality if you use = or ==. You get numeric equality if you use -eq. If test uses string equality, then it just checks each character of the arguments on both sides of the operator, to make sure each character is the same. (Numeric equality treats the arguments on both sides as a number.) You can use double quotes (or not) around both arguments for both string equality and numeric equality (although if you have a number with a space in it, you have an invalid number anyway).
The only thing you have to ensure is that there's exactly one word on both sides of the = or == operator, otherwise test will give you an error. (And = acts the same way as ==, so which one you use is purely a matter of style.) The only way to ensure there's exactly one word is to use double quotes when substituting a variable -- but if you know beforehand that there's no possible way the variable could ever have a space or tab or newline in its contents, and can never be empty, then you could conceivably get away with omitting the quotes. (Still, I'd leave them, because the code that sets the variable might later start putting spaces in, or leaving the variable blank. If that happens, and you didn't quote the substitutions, you'll have to go back later and double check them all.)
In short, my confusion is, if we shoule write "$a" to get the string "love", then, WHAT IS $a after all? What we get by writing a simple $a ? In your example, $a is love, and "$a" is "love" (then the shell goes through the rest of the command interpretation sequence, which is documented in the bash manpage, but is pretty hard to read). The second variant doesn't get split into multiple words if there's any whitespace in its value. :)
So in a sequence like:
a="fdsfsd fdd"
echo $a
echo "$a" the first echo command would be split into three words after quote removal: echo, fdsfsd, and fdd. The second echo command would be split into two words after quote removal: echo, and "fdsfsd fdd" (but without the quotes). Of course both would do the same thing, but they get interpreted differently.
Thanks to your kind and detailed lecture, I have found out that when the value of a shell variable has no space in it:
1)Both has same effect or semantics
a=y
a="y"
2)Also these have a same effect or semantics
while [ "$a" = "y" ]
while [ $a = "y" ]
while [ $a = y ]
In other words, if there's no space, both $a and "$a" represents/denotes a same string "y" or "love" or "fdsfsfa" or whatever. And, love and "love" are same on *nix shell script.
Now my confusion around $a and "$a" has disappeared. Thanks again!
bwkaz
05-29-2007, 06:33 PM
Yep, that's pretty much it. :)