Brackets in if condition: why am I getting syntax errors without whitespace?

9,145

Solution 1

[ is neither a metacharacter nor a control operator (not even a reserved word; same for ]) thus it needs whitespace around it. Otherwise the shell "sees" the command [01=01] instead of the command [ with the separate parameters 01, =, 01, and ]. Each operator and operand needs to be a separate argument to the [ command, so whitespace is necessary around the operators as well.

if [ "$month" = "01" ]

[$month="01"] is a wildcard pattern matching any of the characters in $month or "01. If it doesn't match anything, it's left alone.

If there is a semicolon after the closing bracket, you don't need a space before it, because the semicolon is always part of a separate token.

if [ "$month" = "01" ]; then

The same goes for bash's (and ksh's and zsh's) double bracket syntax.

More than one condition

There are two ways to combine conditions:

  1. within [

  2. with separate [ commands combined with && or ||

Grouping with brackets is probably easier within [.

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

The first one should be avoided as it's unreliable (try for instance with month='!'). Problems with strange variable content can be avoided by using the safe string (if there is one) first; or by using [[/]] instead of [/]:

if [ "01" = "$month" -a "01" = "$day" ]

Solution 2

Another way to write it:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac
Share:
9,145

Related videos on Youtube

Kumar1
Author by

Kumar1

Updated on September 18, 2022

Comments

  • Kumar1
    Kumar1 almost 2 years

    I am using the below script to move two days back when script runs at starting two days of the year and also check first and second days of every month and move two days back.

    if [$month="01"] && [$day="01"]; then
            date="$last_month/$yes_day/$last_year"
            fulldate="$last_month/$yes_day/$last_year"
    else
            if [$month="01"] && [$day="02"]; then
                    date="$last_month/$yes_day/$last_year"
                    fulldate="$last_month/$yes_day/$last_year"
            else
                    if [ $day = "01" ]; then
                            date="$last_month/$yes_day/$year"
                            fulldate="$year$last_month$yes_day"
                    else
                            if [ $day = "02" ]; then
                                    date="$last_month/$yes_day/$year"
                                    fulldate="$year$last_month$yes_day"
                            else
                                    date="$month/$yes_day/$year"
                                    fulldate="$year$month$yes_day"
                            fi
                    fi
            fi
    fi
    

    But my bad am getting the below error message

    Etime_script.sh: line 19: [06=01]: command not found
    Etime_script.sh: line 24: [06=01]: command not found
    
    • Shawn J. Goff
      Shawn J. Goff about 10 years
      The given answers are correct; you need whitespace after [. Additionally, look into the elif statement; it will help you clean things up. Also, the semicolons after the if statements are not necessary, but are also not incorrect, just strange.
    • goldilocks
      goldilocks about 10 years
      @ShawnJ.Goff They are necessary if you concatenate the next line (if [ ... ]; then), so not that unusual.
  • Kumar1
    Kumar1 about 10 years
    How we can match the two condition in if , like month value == day value if [$month="01"] && [$day="01"]; am expecting 01 && 01 true then print below conditions or move to else statement
  • Hauke Laging
    Hauke Laging about 10 years
    @AshokSanganahalli I have extended my answer.
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    [ when -a/-o are not used is always reliable with POSIX compliant shells. There's no advantage whatsoever in using -a/-o over &&/||. I would definitely discourage its use. Note that [[ is not POSIX.
  • Jakob Bennemann
    Jakob Bennemann about 10 years
    +1 for case statement. If you have more than one elif, you should probably be using case.