在Bash中进行字符串比较。[[: not found。

227

我正在尝试在bash中比较字符串。我已经在stackoverflow上找到了如何执行此操作的答案。在我的脚本中,我正在使用Adam在提到的问题中提交的代码:

#!/bin/bash
string='My string';

if [[ "$string" == *My* ]]
then
  echo "It's there!";
fi

needle='y s'
if [[ "$string" == *"$needle"* ]]; then
  echo "haystack '$string' contains needle '$needle'"
fi

我还尝试了来自Ubuntu论坛的方法,你可以在第2篇帖子中找到。

if [[ $var =~ regexp ]]; then
  #do something
fi

在这两种情况下,我都收到了错误消息:
[[: not found

我做错了什么?

我可能做错了,但是对我来说,始终使用单个方括号都有效。 - Markus Unterwaditzer
1
/bin/bash --version 命令会打印什么? - themel
4
在这种情况下,[不起作用,因为它不支持模式匹配。 - Ansgar Wiechers
这通常意味着你运行了 sh yourscript 而不是 bash yourscript;如果你使用 sh 覆盖了 #!/bin/bash 的 shebang,它将不起作用。 - undefined
10个回答

256

[[ 是一个bash内置命令。您的 /bin/bash 似乎不是真正的bash。

从评论中得知:

在文件顶部添加#!/bin/bash


5
当您运行/bin/bash -c "type [["时,是否会得到相同的结果? - Ansgar Wiechers
52
这件事情发生在我身上是因为我忘记在文件开头添加 #!/bin/bash - morphatic
31
因为我使用了sh来运行脚本,所以发生了这种情况,让我感到非常沮丧。现在,我必须重新做之前撤销的所有事情,才能找到这个答案。 - Louis Loudog Trottier
1
我希望我能给你更多的赞...浪费了太多时间。 - Dan O'Boyle
谢谢!刚刚意识到我是个白痴。 - Paul Danelli
显示剩余2条评论

220

你是如何运行你的脚本的? 如果你是用

$ sh myscript

你应该尝试:

$ bash myscript

或者,如果这个脚本是可执行的:

$ ./myscript

shbash是两种不同的shell。在第一种情况下,您将脚本作为参数传递给sh解释器,而在第二种情况下,您可以在第一行中决定使用哪个解释器。


我以这种方式收到了“权限被拒绝”的错误。使用sudo ./myscript仍然显示“命令未找到”。 - user1581900
12
执行 chmod +x myscript 命令后,再次运行即可,无需使用sudo。 - Akos K
2
你是如何调用你的脚本的? - Akos K
就像你所说的那样,通常我会使用“$sh myscript.sh”来调用它。第二次,在执行了“chmod +x myscript.sh”之后,我使用“./myscript.sh”来调用它。 - user1581900
6
当您通过sh myscript.sh运行脚本时,预计会出现错误,因为/bin/sh模拟的是Bourne shell,其中[[不是内置命令。但是,如果通过./script.sh运行脚本,则不应产生错误,因为这种情况下shebang应该会导致使用/bin/bash - Ansgar Wiechers
请参阅“sh”和“bash”的区别,该文章详细阐述了它们之间的差异。 - tripleee

85

你的脚本中第一行是:

#!/bin/bash
或者
#!/bin/sh

这个错误信息是由sh shell产生的,而不是bash。


2
我也遇到了第一行缺失的问题,导致了作者提到的错误! - Anonymous

28

如@Ansgar所提到的,[[是Bashism,即内置于Bash中,其他Shell不可用。如果你想让你的脚本具有可移植性,请使用[。比较运算也需要不同的语法:将==改为=

if [ $MYVAR = "myvalue" ]; then
    echo "true"
else
    echo "false"
fi

在Ubuntu 16.04和(sh->)dash 0.5.8-2.1ubuntu2上进行了一些测试,并发现[与“-eq”等组合使用效果良好。有关此上下文中比较运算符的类似信息可以在此处找到:https://dev59.com/Hmgv5IYBdhLWcg3wF9BP - 我还按照下一个链接建议的(( ))评估运算符进行了检查,但对于我最小侵入性的更改来说似乎失败了/或者/它需要更深层次的代码更改。http://www.softpanorama.org/Scripting/Shellorama/Control_structures/comparison_operators.shtml - Alexander Stohr

17

我在安装Heroku Toolbelt时遇到了这个问题。

以下是我解决这个问题的方法。

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ago 15  2012 /bin/sh -> dash

正如您所看到的,/bin/sh是链接到“dash”(而不是bash),而[[是bash语法糖。因此我只是将链接替换为/bin/bash。注意在系统中使用rm时要小心!

$ sudo rm /bin/sh
$ sudo ln -s /bin/bash /bin/sh

7
在我看来,覆盖默认的 sh 不是一个明智的选择。用 sh 运行的 shell 应该能够与 dash 兼容;如果不能兼容,那么脚本中存在漏洞。如果需要使用 bash 的功能,请使用 bash 而不是 sh - tripleee
4
说实话,这听起来很糟糕。 - MrVaykadji
2
我同意,这只是一个丑陋的解决方法。一种类似但更好的解决方法是使用 update-alternatives (在基于 debian 的 linux 中),就像这样 https://justinconover.wordpress.com/2012/05/14/ubuntu-changing-dash-to-bash/ 但最终结果是相同的。 - jperelli

10

如果您知道您正在使用bash,但仍然收到此错误,请确保您在if关键字前后加上空格。

[[1==1]] # This outputs error

[[ 1==1 ]] # OK

4

运行脚本时请指定bash而不是sh。我个人注意到在Ubuntu 12.10下它们是不同的:

bash script.sh 参数0 ... 参数n


这个对我有用! - Djamillah

3
在终端中执行以下命令:
sudo update-alternatives --install /bin/sh sh /bin/bash 100

0
我在Mac上遇到了同样的错误,但是这是因为我在输入"["之前按住了Option键,并且输入了一个空格。所以这个空格字符并不是我想要输入的空格字符,而是一个"非断行空格"。在文本编辑器中看不见,但却导致了一个"[[: command not found"的错误。

这并没有真正回答问题。如果你有其他问题,可以点击提问来提出。如果你想在这个问题有新的回答时收到通知,你可以关注此问题。一旦你拥有足够的声望,你还可以添加悬赏以吸引更多关注。- 来自评论 - Yogendra

0

将文件设为可执行文件,然后无需使用 sh 命令直接执行。

  1. 通过 $ chmod +x 文件名 将其设为可执行文件
  2. 然后用 ./文件名 替代 sh 文件名 来执行

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接