如何比较Bash中'if'语句中的两个字符串变量?

Mr *_*ubs 572 bash scripting if-statement

我正在尝试使用Bash(使用Ubuntu)获得一个if声明:

#!/bin/bash

s1="hi"
s2="hi"

if ["$s1" == "$s2"]
then
  echo match
fi
Run Code Online (Sandbox Code Playgroud)

我尝试了各种形式的if语句,使用[["$s1" == "$s2"]],有和没有引号,使用=,==-eq,但我仍然得到以下错误:

[hi:命令未找到

我查看了各种网站和教程并复制了这些内容,但是它不起作用 - 我做错了什么?

最后,我想说是否$s1包含$s2,所以我该怎么做?

我刚刚解决了空位...:/我怎么说包含?

我试过了

if [[ "$s1" == "*$s2*" ]]
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

mar*_*cog 806

对于字符串比较,请使用:

if [ "$s1" == "$s2" ]
Run Code Online (Sandbox Code Playgroud)

对于a包含b,使用:

if [[ $s1 == *"$s2"* ]]
Run Code Online (Sandbox Code Playgroud)

(并确保在符号之间添加空格):

坏:

if ["$s1" == "$s2"]
Run Code Online (Sandbox Code Playgroud)

好:

if [ "$s1" == "$s2" ]
Run Code Online (Sandbox Code Playgroud)

  • 在第一种情况下,双等号是错误的.Bash容忍它,但便携式变体是`if ["$ s1"="$ s2"]`.另见[Rahul的回答](http://stackoverflow.com/a/36279399/874188) (13认同)
  • @Sangimed,`[`是**命令**(实际上是命令`test`的替代名称); 如果运行`哪个[`,你会看到它实际上是磁盘上的可执行文件(即使shell可能提供内置实现作为性能优化).就像你必须在你希望它打印的文件名之前的命令`ls`的名字之间加一个空格一样,你需要在`[`命令的名称及其第一个参数之后放一个空格,并且它被传递的每个参数之间(如果被调用为`[`而不是`test`,它期望它的最后一个参数是`]`). (13认同)
  • http://stackoverflow.com/a/229606/376454我不得不使用这个答案将变量与固定字符串进行比较. (4认同)
  • IRC挑剔的人告诉我你应该使用if [["$ s1"=="$ s2"]]或案例. (3认同)
  • POSIX `test` 仅指定 `=` 作为字符串比较运算符。`==` 是一个不可移植的扩展。因此,使用 `[ "$str1" = "$str2" ]` 而不是 `[ "$str1" == "$str2" ]` 是一个更好的习惯(这在基线 POSIX shell 上不起作用,例如短跑)。 (3认同)
  • 嗨,我想知道为什么这不好 -> 如果 ["$s1" == "$s2"] 空格有什么意义? (2认同)

unw*_*ind 157

你需要空格:

if [ "$s1" == "$s2" ]
Run Code Online (Sandbox Code Playgroud)

  • 只想说要确保在开始和结束方括号之间留一个空格和`"$ s1"=="$ s2"`语句,否则它将无效.此外,这也有效:`如果测试"$ s1"="$ s2"` (14认同)
  • `==`不适用于ash,dash或其他地方`test`的基线POSIX实现.请改用`=`. (5认同)
  • 这都是关于空间:)) (3认同)

小智 140

你应该小心在'['和双引号的符号之间留一个空格,其中变量包含:

if [ "$s1" == "$s2" ]; then
#   ^     ^  ^     ^
   echo match
fi
Run Code Online (Sandbox Code Playgroud)

^S显示你需要离开的空白.

  • 非常感谢指出必要的空间.解决了我的问题.刚刚开始使用bash,似乎很多时候空格都会导致错误,即声明变量等. (4认同)
  • 包含`;的加分点;然后`和`fi`部分。 (2认同)
  • `==`不适用于ash,dash或其他地方`test`的基线POSIX实现.请改用`=`. (2认同)

Abd*_*DMA 33

我建议这个:

if [ "$a" = "$b" ]
Run Code Online (Sandbox Code Playgroud)

注意打开/关闭括号和变量之间的空白区域以及包裹"="符号的空格.

另外,请注意脚本标题.你是否使用它并不是一回事

#!/bin/bash
Run Code Online (Sandbox Code Playgroud)

要么

#!/bin/sh
Run Code Online (Sandbox Code Playgroud)

这是源头.


小智 17

我会建议:

#!/bin/bash

s1="hi"
s2="hi"

if [ $s1 = $s2 ]
then
  echo match
fi
Run Code Online (Sandbox Code Playgroud)

没有双引号,只有一个等于.

  • 为什么要省略双引号?它们是可选的,但在这种有限的特定情况下是无害的,但在许多现实世界中,删除它们将是一个严重的错误.另见http://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-variable (5认同)
  • 尝试使用`s1 ='*'`和`s2 ='*'`,你会发现忽略双引号是一个严重的错误. (2认同)

Mik*_*e Q 16

Bash4 +示例.注意:当单词包含空格等时,不使用引号会导致问题.总是引用bash IMO.

以下是BASH4 +的一些示例:

例1,检查字符串中的"是"(不区分大小写):

if [[ "${str,,}" == *"yes"* ]] ;then
Run Code Online (Sandbox Code Playgroud)

例2,检查字符串中的"是"(不区分大小写):

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

例3,检查字符串中的"是"(区分大小写):

 if [[ "${str}" == *"yes"* ]] ;then
Run Code Online (Sandbox Code Playgroud)

例4,检查字符串中的"是"(区分大小写):

 if [[ "${str}" =~ "yes" ]] ;then
Run Code Online (Sandbox Code Playgroud)

例5,完全匹配(区分大小写):

 if [[ "${str}" == "yes" ]] ;then
Run Code Online (Sandbox Code Playgroud)

例6,完全匹配(不区分大小写):

 if [[ "${str,,}" == "yes" ]] ;then
Run Code Online (Sandbox Code Playgroud)

例7,完全匹配:

 if [ "$a" = "$b" ] ;then
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。我敢打赌,如果它离顶部不是太远的话,它会得到更多的支持。 (2认同)

Rah*_*iya 14

这个问题已经有了很好的答案,但在这里看来,使用单个等号和双等号之间存在轻微的混淆

if [ "$s1" == "$s2" ]
Run Code Online (Sandbox Code Playgroud)

主要区别在于您使用的是哪种脚本语言.如果您正在使用bash,那么请#!/bin/bash在脚本的开头包含并将脚本保存为filename.bash.要执行使用bash filename.bash- 那么你必须使用==.

如果您正在使用sh,请使用#!/bin/sh并将脚本另存为filename.sh.要执行使用sh filename.sh- 那么你必须使用单一=.避免混合它们.

  • 断言"你必须使用`==`"是不正确的.Bash支持`=`和`==`.此外,如果你在脚本的开头有`#!/ bin/bash`,你可以使它成为可执行文件并像`./ filename.bash`一样运行它(不是文件扩展名很重要). (4认同)

qwe*_*rty 9

$ if [ "$s1" == "$s2" ]; then echo match; fi
match
$ test "s1" = "s2" ;echo match
match
$
Run Code Online (Sandbox Code Playgroud)

  • 在Bash中可以容忍双等号,但在其他一些方言中则不然.为了便于携带,单个等号应该是首选,如果你只针对Bash,那么双括号`[[`扩展将在多功能性,健壮性和便利性方面更胜一筹. (3认同)

小智 7

我现在无法访问linux盒子,但是[实际上是一个程序(和内置的bash),所以我认为你必须在[和第一个参数之间]放置一个空格.

还要注意字符串相等运算符似乎是单个=


Mik*_*keW 6

这比答案更清晰!是的,线索在错误消息中:

[hi:命令未找到

这表明你的"hi"已被连接到"[".

与更传统的编程语言不同,在Bash中,"["是一个命令就像更明显的"ls"等 - 它没有被特别对待,因为它是一个符号,因此"["和(替换)"$ s1 "在你的问题中彼此紧挨着的,加入(对Bash来说是正确的)然后它试图在那个位置找到一个命令:[hi - Bash不知道.

在C和其他一些语言中,"["将被视为一个不同的"字符类",并且将与以下"hi"脱节.

因此,在打开"["后需要一个空格.


mpa*_*pis 5

使用:

#!/bin/bash

s1="hi"
s2="hi"

if [ "x$s1" == "x$s2" ]
then
  echo match
fi
Run Code Online (Sandbox Code Playgroud)

在里面添加额外的绳子可以使其更安全。

您还可以对单行命令使用另一种表示法:

[ "x$s1" == "x$s2" ] && echo match
Run Code Online (Sandbox Code Playgroud)

  • “更安全”是什么意思?为了完整和清晰起见,解释任何此类资格非常重要。 (4认同)
  • 事实是,这并不安全,现在我知道如果您不引用它会更安全,并且如果其中一个为空,这样可以防止语法错误 (4认同)