3

I have this code

STATUS=`echo "test"`


if [ $STATUS == "test" ]; then
   exit 0
fi

I have tried everything and i am not able to make it true.

I tried

"$STATUS" == "test"
eval $STATUS == "test"
${STATUS[@]} == "test"

The only thing that worked is

$STATUS == \"test\"
CephBirk
  • 103
Mirage
  • 121
  • 1
  • 1
  • 4
  • 2
    It works as expected for me; add set -x before this to see what's happening in your situation. BTW, if [ "$STATUS" = "test" ]; then (with double-quotes around the variable and a single = sign) is the preferred form. Also, I recommend avoiding all-caps variable names (like STATUS) -- there are a bunch of all-caps vars with special meaning, and it's easy to re-use one of those and get weird results. Lower- and mixed-case variable names are safer. – Gordon Davisson Jun 29 '18 at 05:29
  • 1
    Please [edit] your question and explain what happens. "It does not work" is a lousy bug report. – Kusalananda Jun 29 '18 at 06:46
  • Above your if statement, add echo "STATUS=<$STATUS>". Whatever is reported inside the angle brackets is the value you need to test. – Chris Davies Jun 29 '18 at 07:00
  • 1
    Based on your somewhat poor description I suspect your starting case is actually STATUS=`echo '"test"'`, ie STATUS='"test"'. – Chris Davies Jun 29 '18 at 07:02
  • you are right roamia – Mirage Jun 29 '18 at 21:59

3 Answers3

8

The code in the question works, meaning it will execute the exit 0 statement.

Your

STATUS=`echo "test"`

is the same as

STATUS="test"

and (in this case) as

STATUS=test

i.e. the variable STATUS is assigned test as the value (there are no double quotes in the value).

To test this against the value test, do

if [ "$STATUS" = "test" ]

or

if [[ $STATUS == "test" ]]

If STATUS has the value "test", as in

STATUS='"test"'

then use that string in the comparison:

if [ "$STATUS" = '"test"' ]

or

if [[ $STATUS == '"test"' ]]

See also:

Kusalananda
  • 333,661
  • Looks like you beat me to answering about trying the [[ operator. Your answer got posted as I was writing mine. – TheNH813 Jun 29 '18 at 07:10
  • Might I add another way to place an actual " inside a variable is by escaping it with , although it looks ugly. STATUS=""test"" – TheNH813 Jun 29 '18 at 07:14
  • @TheNH813 Yes, that's ugly, and there is no reason to double quote the string assigned in this case. I'd just use single quotes instead: STATUS='"test"'. – Kusalananda Jun 29 '18 at 07:24
1

Those escaped quotes in \"test\" make me think that there's some confusion about the quoting rules of shell, because the first piece of code works as intended and $STATUS == \"test\" shouldn't (unless you wrote STATUS=`echo '"test"'` or something similar).

To properly clarify this confusion, it is needed to explain some shell concepts.


Quoting

In POSIX shells, quoting is one of the most important mechanisms. Unfortunately, it is also a very confusing topic and, when used incorrectly, a big source of bugs and weird behavior in scripts.

The basic rules are the following:

  1. Escape character \: Preserves the literal value of the next character that follows, with the exception of <newline>.
  2. Double quotes ": Preserves the literal value of all characters within the quotes, with the exception of $, `, \ and, when history expansion is enabled, !.
  3. Single quotes ': Preserves the literal value of all characters within the quotes, without exceptions.

Command substitution

Command substitution allows the output of a command to replace the command itself. Its syntax is either $(command) or `command`, although the former is prefered.

Test command

The test command (also known as [ in POSIX and [[ in shells like bash, ksh and zsh) let you use many useful conditional and arithmetical expressions. For example, it can check if a given regular file exists and is readable, if two strings are equal or if a number is greater than another.


Now, analyzing the code:

STATUS=`echo "test"`

The command substitution here is useless, as it could have been written as STATUS="test". Note that the double quotes are not printed by echo, so STATUS holds test as its value.

if [ $STATUS == "test" ]; then
   exit 0
fi

Here are, at least, 3 potential flaws:

  1. The unquoted $STATUS could be affected by word splitting.
  2. == is non-POSIX syntax. Use = if you care about portability.
  3. if and exit 0 are useless in this scenario as [ already does the intended job.

Also, note that, as the previous line of code, the double quotes are not taken literally, so the resulting command (after expansion and quote removal) is [ test = test ], which is true.


But if your goal was to have "test" as the value of STATUS, then

STATUS=\"test\"
STATUS="\"test\""
STATUS='"test"'

are all valid assignments and

[ "$STATUS" = \"test\" ]
[ "$STATUS" = "\"test\"" ]
[ "$STATUS" = '"test"' ]

are all valid conditional expressions.

nxnev
  • 3,654
0

The solution to this problem may differ based on what shell you are using. Also, ensure that $STATUS contains "test" before the compare with a "echo $STATUS" line in your script. Checking the contents of variables is very helpful for debugging. Although unlikely, there is a small chance some other program is setting it, in which case it will obviously fail.

Generally speaking though, the code you have written SHOULD work. If it isn't the problem might have to be with any other code in the script, the shell itself or some other program interfering. You can try exporting the variable system wide with export to ensure it's set properly. This should override any interfering values. Keep in mind if another program is interfering, it might not like it's variables getting changed.

As a reference, I will provide the following information:

The best way to set a variable to a simple state like "test" is simply:

VARIABLE="value"

While you can use echo to return text into a variable, for strings like test, there's no reason for it. Unless you intend to insert control characters like line feeds using echo -e or printf.

The recommended way to compare a string is with either of these:

if [ "$VARIABLE" = "value" ]; then
if [[ $VARIABLE == value ]]; then

If you haven't already tried it, try using the newer [[, also known as extended test, instead of [, also known as the classic test.

http://wiki.bash-hackers.org/commands/classictest

http://wiki.bash-hackers.org/syntax/ccmd/conditional_expression

These are great resources to help you with getting further information if you want to know all the details about the test operators.

TheNH813
  • 109
  • 1
    Don't dereference the variable when you assign to it ($VARIABLE="value" should not have $). You also mix up [ .. = .. ] and [[ .. == .. ]]. – Kusalananda Jun 29 '18 at 07:25
  • 1
    And in addition [[ VARIABLE = value ]] will compare the two literal strings against each other – ilkkachu Jun 29 '18 at 08:11
  • @Kusalananda Sorry. I fixed the $ before the variable. Not sure why I put that there to be honest. – TheNH813 Jun 29 '18 at 19:48
  • @ilkkachu Can you explain what you mean by that? In regards to literal comparison with [[ operator, I read this on the bash hackers wiki: "But note¹, quoting the pattern forces a literal comparison.", so it made sense that it wouldn't perform a literal comparison if it wasn't quoted. I'l be honest, I might know Bash fairly well, but I rarely if ever use [[. – TheNH813 Jun 29 '18 at 19:52
  • 1
    @TheNH813 He means you have to dereference VARIABLE: if [[ $VARIABLE == "value" ]]. Also note == inside [[ ... ]], and = inside [ ... ]. – Kusalananda Jun 29 '18 at 20:04
  • 1
    @TheNH813 In addition to what Kusalananda said: there are places where there is no need to write the $ when referencing a variable (((a + b)), ${array[i]}), but [[ is not one of them. – nxnev Jun 29 '18 at 20:09
  • I strongly remember if [ "$variable"="some value" ]; then failing with "integer expression expected", but apparently it doesn't. Don't know why I'v been using [ ... == ... ] instead of [ ... = ... ] for all years then. Appears it doesn't hurt anything, but is unnecessary. Thanks for the advice, everyone. I'l edit my answer to reflect the correct information. – TheNH813 Jun 29 '18 at 21:10
  • 1
    @TheNH813 The "integer expression expected" error appears when, in arithmetical expressions, one of the operands is not a number. For example: [ foo -eq 5 ] throws the error but [ 5 -eq 5 ] does not. [ … == … ] does not break anything in Bash and some other shells, but [ … = … ] is the correct way if you aim to write POSIX-compliant scripts. – nxnev Jun 29 '18 at 22:15