1

How would be the correct bash syntax for something like this:

if [ "$actual" == "$expected" ]; then 
  doNothing
else 
  echo "Error: actual: $actual. Expected: $expected"
fi

I am looking for something that works for all possible values of the variables "actual" and "expected". The content of the variables must not be interpreted/evaluated/expanded in any way. The script does not need to be portable (a bash only solution is ok).

Gustave
  • 3,359
  • 4
  • 31
  • 64

3 Answers3

4

You could use the simplest do-nothing statement available:

if [ "$actual" = "$expected" ]; then 
  :
else 
  echo "Error: actual: $actual. Expected: $expected"
fi

(Note: One = not two in [/test.)

But a better idea is to just invert the test and remove the need for that entirely:

if [ "$actual" != "$expected" ]; then
  echo "Error: actual: $actual. Expected: $expected"
fi
Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
  • I just read an accepted answer here (I cannot find it again) that suggests to use == instead of = . What is the difference? For simple cases both seem to work. What would be the negation of == ? Is it !== ?. – Gustave Jul 15 '15 at 12:44
  • The POSIX `[`/`test` uses `=` for equality and `!=` for inequality ([ref](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128_05)). bash (and likely many other shells) accept `==` in that usage as well but it isn't strictly spec. The bash-specific `[[` built-in test syntax ([ref](http://www.gnu.org/software/bash/manual/bashref.html#index-_005b_005b)) uses `==`/`!=` (but also accepts `=` for sanity's sake). – Etan Reisner Jul 15 '15 at 12:49
  • There seems to be no consensus if [ or [[ should be used. – Gustave Jul 15 '15 at 12:56
  • 1
    They are different. `[` is portable. `[[` is a bash-ism. `[[` has some nice safety properties that `[` does not (but also at least one down-side, see my comment on DevSolar's answer). `[[` supports some tests that `[` doesn't as well. – Etan Reisner Jul 15 '15 at 12:57
  • What do you mean with "isn't strictly spec"? I thought the different shells are not compatible anyway? – Gustave Jul 15 '15 at 13:27
  • There is a spec, I linked to a section of it before, for how POSIX shells should function. A common-base if you will. Not all shells adhere to that, not all do so as completely as others, etc. – Etan Reisner Jul 15 '15 at 13:51
1

Did you try:

if [ "$actual" != "$expected" ]; then 
  echo "Error: actual: $actual. Expected: $expected"
fi
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • 3
    `-ne` is a numeric comparison `!=` is string comparison. They are not equivalent. – Etan Reisner Jul 15 '15 at 12:29
  • What is the exact difference? A variable can contain a numerical value, too, can't it? Is there a difference between a variable containing the number 1 or the text 1? – Gustave Jul 15 '15 at 12:48
  • The difference is when the value is **not** a number. `[ 5 = 5 ]` and `[ 5 -ne 3 ]` will both be true but `[ 5 -ne foo ]` will be a runtime error whereas `[ 5 != foo ]` will be false. – Etan Reisner Jul 15 '15 at 12:51
  • What should I use if I don't know in advance of the variables contain a string or numerical value or something else? – Gustave Jul 15 '15 at 12:55
  • 1
    @etan: 07 and 7 are the same number and different strings. Just as one example. – rici Jul 15 '15 at 15:07
  • @rici Very true. I obviously wasn't thinking clearly when I wrote that. – Etan Reisner Jul 15 '15 at 15:09
  • Which to use if you don't know what you are going to need to compare depends entirely on where your data is going to come from and what you need to correctly compare. Neither set of comparison operators will Just Work for all input sanely (without error checking/validation/etc.) around it. – Etan Reisner Jul 15 '15 at 15:10
-1
if [[ $actual != $expected ]]
then
    echo "Error: actual: $actual. Expected: $expected"
fi

Using the builtin [[ has several advantages over test / [. For one, you don't get bitten if you don't quote variables containing whitespace.

[[ ]] also offers < and > for locale-aware lexicographic sorting, regular expression matching, and =~. Check man bash.

(Note Etan's comment though on at least one dissenting opinion. I haven't yet made up my mind whether this is a disadvantage or a feature to be exploited, but it is sure surprising.)

There's also the thing with putting then on a separate line, but that's just personal preference.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • Why not expand on the advantages of `[[` over `[`? – arco444 Jul 15 '15 at 12:37
  • 1
    `[[` also has (at least) one down-side with numeric comparisons. It recursively expands non-numeric values (see my question [here](http://stackoverflow.com/q/29980940/258523) for a little about that). – Etan Reisner Jul 15 '15 at 12:38
  • @arco444: I added the difference that counts in the scope of the question. – DevSolar Jul 15 '15 at 12:49
  • @Etan: Good catch and caveat. – DevSolar Jul 15 '15 at 12:49
  • What are those advantages? What is the thing with then on a separate line? What is the exact difference of [[ and [ ? – Gustave Jul 15 '15 at 12:49
  • @Gustave: A semicolon in bash seperates multiple commands in one line. I prefer not to do that, for aesthetic and practical reasons (like, line numbers referring to a single command, unambiguously). If you follow through on that style, `then` has to go on a separate line. It's like ANSI vs. Egyptian brackets, preference really. – DevSolar Jul 15 '15 at 13:12
  • @DevSolar: What do you mean with "get bitten if you don't quote variables containing whitespace"? – Gustave Jul 15 '15 at 13:24
  • I don't understand this fully, but I guess that there are sitiuations where the values that the variables contain are interpreted/evaluated/expanded before the actual comparison is done. What should I do if I want to ensure that the values are taken as they are under all circumstances? – Gustave Jul 15 '15 at 13:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83336/discussion-between-devsolar-and-gustave). – DevSolar Jul 15 '15 at 13:42