Как сравнить две строковые переменные в операторе if в Bash? [Дубликат]

457

Я пытаюсь заставить оператор if работать в Bash (используя Ubuntu):

#!/bin/bash

s1="hi"
s2="hi"

if ["$s1" == "$s2"]
then
  echo match
fi

Я пробовал различные формы инструкции if, используя [["$s1" == "$s2"]], с кавычками и без них, используя =, == и -eq, но я все еще получаю следующую ошибку:

[привет: команда не найдена

Я просмотрел различные сайты и учебники и скопировал их, но он не работает - что я делаю неправильно?

В конце концов, я хочу сказать, если $s1 содержит $s2, так как я могу это сделать?

Я просто обработал пробел.:/Как я могу сказать, содержит?

Я пробовал

if [[ "$s1" == "*$s2*" ]]

но это не сработало.

Теги:
if-statement
scripting

12 ответов

657
Лучший ответ

Для сравнения строк используйте:

if [ "$s1" == "$s2" ]

В a содержится b, используйте:

if [[ $s1 == *"$s2"* ]]

(и не забудьте добавить пробелы между символами):

плохо:

if ["$s1" == "$s2"]

хорошо:

if [ "$s1" == "$s2" ]
  • 4
    stackoverflow.com/a/229606/376454 Мне пришлось использовать этот ответ, чтобы сравнить переменную с фиксированной строкой.
  • 2
    Придирчивые ребята из IRC говорят мне, что вы должны использовать if [["$ s1" == "$ s2"]] или case.
Показать ещё 5 комментариев
150

Вам нужны пробелы:

if [ "$s1" == "$s2" ]
  • 14
    Просто хотел сказать, чтобы не было пробела между начальными и конечными квадратными скобками и оператором "$s1" == "$s2" иначе он не будет работать. Кроме того, это тоже работает: if test "$s1" = "$s2"
  • 3
    Это все о космосе :))
Показать ещё 2 комментария
122

Вы должны быть осторожны, чтобы оставить пробел между знаком "[" и двойными кавычками, где переменная содержит это:

if [ "$s1" == "$s2" ]; then
#   ^     ^  ^     ^
   echo match
fi

^ показывает пробелы, которые вам нужно оставить.

  • 3
    Большое спасибо за указание необходимого места. Решил мою проблему. Только что начал bash сегодня, кажется, много раз пробелы могут вызвать ошибку, то есть объявление переменных и т. Д.
  • 1
    Бонусный балл за включение ; then и fi части.
Показать ещё 1 комментарий
28

Я предлагаю следующее:

if [ "$a" = "$b" ]

Обратите внимание на пустое пространство между скользящими и закрывающимися скобками и переменными, а также белые пробелы, обертывающие знак "=".

Кроме того, будьте осторожны с заголовком script. Это не то же самое, если вы используете

#!/bin/bash

или

#!/bin/sh

Здесь источник.

  • 1
    Повышение, но всегда будьте осторожны при чтении АБС. Ссылка на более авторитетный источник, вероятно, будет предпочтительнее.
  • 0
    Спасибо за совет, уверен, более авторитетный источник более точен.
Показать ещё 2 комментария
11

Я бы предложил:

#!/bin/bash

s1="hi"
s2="hi"

if [ $s1 = $s2 ]
then
  echo match
fi

Без двойных кавычек и только с одним равным.

  • 0
    Да, это правда, я пропустил пробелы. С "[$ s1 = $ s2]" это работает.
  • 5
    Почему вы опускаете двойные кавычки? Они необязательны, но безвредны в этом ограниченном конкретном случае, но удаление их будет серьезной ошибкой во многих реальных ситуациях. Смотрите также stackoverflow.com/questions/10067266/…
Показать ещё 1 комментарий
9

У этого вопроса уже есть большие ответы, но здесь кажется, что есть небольшая путаница между использованием равных равных и двойных равных в

if [ "$s1" == "$s2" ]

Основное отличие заключается в том, что вы используете язык сценариев. Если вы используете bash, включите #!/bin/bash в начало script и сохраните script как filename.bash. Для выполнения использования bash filename.bash - тогда вы должны использовать ==.

Если вы используете sh, используйте #!/bin/sh и сохраните script как filename.sh. Для выполнения использования sh filename.sh - тогда вы должны использовать одиночный =. Избегайте их смешения.

  • 4
    Утверждение "вы должны использовать == " неверно. Bash поддерживает оба = и == . Кроме того, если у вас есть #!/bin/bash в начале вашего скрипта, вы можете сделать его исполняемым и запустить его как ./filename.bash (не то, чтобы расширение файла было важным).
  • 0
    Отлично, я думаю, что мне нужно удалить этот ответ сейчас, но будет очень полезно, если вы объясните, почему это не работает, не делая файл исполняемым и запущенным, добавив sh / bash перед именем файла?
Показать ещё 4 комментария
7
$ if [ "$s1" == "$s2" ]; then echo match; fi
match
$ test "s1" = "s2" ;echo match
match
$
  • 3
    Знак двойного равенства допускается в Bash, но не на некоторых других диалектах. Для переносимости предпочтительнее использовать один знак равенства, и если вы нацеливаетесь только на Bash, двойные скобки [[ extension будут превосходить по универсальности, надежности и удобству.
6

У меня нет доступа к linux-боксу прямо сейчас, но [на самом деле это программа (и bash builtin), поэтому я думаю, что вам нужно разместить пробел между [и первым параметром.

Также обратите внимание, что оператор равенства строк представляется одиночным =

  • 0
    Символ [был ссылкой на / bin / test в одно время (или, возможно, наоборот). По-видимому, это больше не относится к Ubuntu 16.04; не знаю, где и когда произошли изменения.
5

Bash4+. Примечание: не использовать кавычки вызовет проблемы, когда слова содержат пробелы и т.д. Всегда указывайте в bash IMO.

Вот несколько примеров Bash4+:

Пример 1, проверьте "да" в строке (без учета регистра):

if [[ "${str,,}" == *"yes"* ]] ;then

Пример 2, проверьте "да" в строке (без учета регистра):

if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

Пример 3, проверьте "да" в строке (с учетом регистра):

 if [[ "${str}" == *"yes"* ]] ;then

Пример 4, проверьте "да" в строке (с учетом регистра):

 if [[ "${str}" =~ "yes" ]] ;then

Пример 5, точное совпадение (с учетом регистра):

 if [[ "${str}" == "yes" ]] ;then

Пример 6, точное совпадение (без учета регистра):

 if [[ "${str,,}" == "yes" ]] ;then

Пример 7: точное совпадение:

 if [ "$a" = "$b" ] ;then
  • 1
    Отличный ответ. Держу пари, что он получит больше голосов, если не будет так далеко от вершины.
5

Это больше разъяснений, чем ответ! Да, ключ находится в сообщении об ошибке:

[привет: команда не найдена

который показывает вам, что ваш "привет" был связан с "[" .

В отличие от более традиционных языков программирования, в Bash, "[" - это команда, как и более очевидная "ls" и т.д. - она ​​не обрабатывается специально только потому, что она является символом, следовательно, "[" и ( замещенные) "$ s1", которые находятся рядом друг с другом в вашем вопросе, соединены (как правильно для Bash), и затем пытается найти команду в этой позиции: [hi - неизвестно Bash.

В C и некоторых других языках "[" будет рассматриваться как другой "класс символов" и будет несовместим со следующим "привет".

Следовательно, вам нужно пространство после открытия "[" .

2

Для версии с чистым Bash и без test, но действительно уродливо, попробуйте:

if ( exit "${s1/*$s2*/0}" )2>/dev/null
then
   echo match
fi

Объяснение: В ( ) открывается дополнительная подоболочка. Он выходит с 0, если был матч, и пытается выйти с $s1, если не было совпадения, которое вызывает ошибку (уродливый). Эта ошибка направлена ​​на /dev/null.

  • 0
    Совсем неплохо. Как объяснение и как регулярное выражение sed. Мне никогда не нужно использовать подоболочку таким образом. Как я знаю, вы можете получить вывод с помощью command или $ (команда). Я уверен, что вы можете проверить это, а затем сделать это лучше.
  • 3
    Это тривиально нарушается в случае, когда s2 содержит глобусы: чтобы исправить это, вам нужно заключить в кавычки расширение $s2 : "${s1/*"$s2"*/0}" . Но есть и другие тонкие ошибки, которые невозможно исправить: например, если s1 - это список из 0 : s1=000000; s2=some_other_stuff будет требовать совпадения. Поэтому я настоятельно рекомендую не использовать этот метод! Еще одна ошибка: s1=--; s2=stuff Начиная с bash 4.4, s1=--help; s2=stuff также будут спамить стандартный вывод.
2
#!/bin/bash

s1="hi"
s2="hi"

if [ "x$s1" == "x$s2" ]
then
  echo match
fi

Добавление дополнительной строки внутри делает ее более безопасной.

Вы также можете использовать другие обозначения для одиночных команд:

[ "x$s1" == "x$s2" ] && echo match
  • 4
    Что значит «более безопасный»? Важно объяснить любую такую квалификацию ради полноты и ясности.
  • 4
    правда это не безопаснее, теперь я знаю, что было бы безопаснее, если бы вы не цитировали его и таким образом предотвращали синтаксическую ошибку, если один из них был пуст
Сообщество Overcoder
Наверх
Меню