Почему равный оператор не работает, если он не окружен пространством?

Я попробовал следующее script

#!/bin/bash
var1="Test 1" 
var2="Test 2"
if [ "$var1"="$var2" ] 
  then 
    echo "Equal" 
  else 
    echo "Not equal"
fi

Он дал мне Equal. Хотя он должен был напечатать Not equal

Только когда я вставил пространство вокруг =, он работал как предполагалось

if [ "$var1" = "$var2" ] 

и напечатано Not equal

Почему так? Почему "$var1"="$var2" не такой же, как "$var1" = "$var2"?

Кроме того, когда я написал if [ "$var1"= "$var2" ], он дал

line 4: [: Test 1=: unary operator expected

Что это значит? Почему его ожидающий унарный оператор?

Ответ 1

test (или [ expr ]) - встроенная функция. Как и все функции в bash, вы передаете его аргументам в виде разделенных пробелами слов.

В качестве справочной страницы для bash встроенных состояний: "Каждый оператор и операнд должны быть отдельным аргументом".

Это просто способ bash и большинство других Unix-оболочек.

Назначение переменных отличается.

В bash присваивание переменной имеет синтаксис: name=[value]. Вы не можете помещать незатребованные пробелы вокруг =, потому что bash не будет интерпретировать это как назначенное вами назначение. bash обрабатывает большинство списков слов как команду с параметрами.

например.

# call the command or function 'abc' with '=def' as argument
abc =def

# call 'def' with the variable 'abc' set to the empty string
abc= def

# call 'ghi' with 'abc' set to 'def'
abc=def ghi

# set 'abc' to 'def ghi'
abc="def ghi"

Ответ 2

Когда оболочка читает

if [ "$var1" = "$var2" ]

он вызывает команду [с 4 аргументами. Независимо от того, является ли [встроенная или внешняя команда несущественной, но может помочь понять, что это может быть внешняя команда /bin/ [. Второй аргумент - буква "=", а четвертый - "]". Однако, когда оболочка читает

if [ "$var1"= "$var2" ]

[получает только 3 аргумента: расширение $var1 с добавлением '=', расширение $var2 и ']'. Когда он получает только 3 аргумента, он ожидает, что последний аргумент будет ']', а первый аргумент будет унарным оператором.

Ответ 3

Чтобы добавить к существующему объяснению, "$var1"="$var2" - это просто одна непустая строка и поэтому всегда оценивается как истина в условном выражении.

[ "$var1"="$var2" ] && echo true

Вышеприведенная команда всегда будет печатать true (даже если var1 и var2 пуст).

Ответ 4

В bash лучше всего использовать [[]]:

x="test"
y="test"
if [[ "${x}" = "${y}" ]]; then
    echo "Equals"
else
    echo "No equals"
fi