【问题标题】:bash script: if use with (conditon) or [condition]bash 脚本:如果与 (condition) 或 [condition] 一起使用
【发布时间】:2014-10-15 23:56:31
【问题描述】:

我对 bash 脚本中的 if 语句有一个微妙的问题:“if”后面应该使用什么类型的括号?

我现在有两个语句都可以工作,但如果我交换 () 和 [] 则不起作用。

1.比较变量名

NAME="dada"
if [ "$NAME" == "dada" ]; then SOME COMMANDS; fi

如果将[]改为(),错误:

dada: command not found

2.使用grep

if ( grep -q "lalala" mytest.txt ); then SOME COMMANDS; fi

如果将()改为[],错误:

[: lalala: binary operator expected

我阅读了 linux man,其中建议使用 []。那么是因为使用了grep吗?能不能说如果在if里面使用另外一个程序,我们应该使用()?

关于双引号的附带问题, 是否有必要在 shell 中引用文本?例如,echo "$NAME" 或 NAME="fadfaj"?

我很困惑,因为当我尝试使用 $NAME 加上一些特殊字符(例如“_”或空格,而我需要使用“\”)时,使用和不使用“”时我得到了不同的行为。

NAME="myfolder"
echo $NAME\_na
echo "$NAME\_na"

输出

myfolder_na
myfolder\_na

我知道这些都是幼稚的问题,但我非常感谢您的所有帮助!

【问题讨论】:

  • 顺便说一下,POSIX不需要test命令支持==作为操作符(一些shell,比如bash,支持作为扩展),所以使用起来更安全= 代替。
  • ...顺便说一句,不要使用括号,除非您想要它们的效果(创建子shell)。 if (foo)if foo 慢,因为它派生了一个子进程,在该子进程内运行foo,然后检查子shell 的返回值。这也意味着,与 if cd directory; the ... 不同——它实际上 确实 更改了当前 shell 中的目录,并根据它是否成功进行了分支——if (cd directory); then ... 实际上不会更改目录你所在的 shell,因为它在子进程中执行 cd,而不是主 shell。
  • 如果你想要一个没有有副作用的分组操作符,那就是花括号,而不是括号。所以:false || {something; something-else; }false || (something; something-else) 更有效。
  • 顺便说一句——不要将额外的问题编辑到一个 SO 主题中。如果您有更多问题,请搜索是否有其他人已经问过,如果没有其他人,请单独询问。否则,您的问题可能会因过于宽泛而被关闭。
  • 非常感谢您提供关于 shell 的额外 cmets/教程!它有很大的帮助,并且可能使我免于将来的调试!我会小心不要在一篇文章中提出多个问题。

标签: linux bash shell


【解决方案1】:

if 关键字后面的东西是一个命令。命令被执行,如果命令成功则条件为真(以0的状态退出),如果失败则为假。

虽然它看起来像 shell 语法,但 [ 符号实际上是命令的名称(恰好内置在 shell 中)。例如,您可以只键入

[ "$NAME" = "dada" ]

在 shell 提示符下,没有if,它将评估相同的条件并设置$?。你也可以这样做:

[ "$NAME" = "dada" ] && echo Yes

][ 命令所需的最后一个参数。除了这个要求,[ 命令等同于test 命令:

if test "$Name" = "data" ; then echo yes ; fi

请注意,我使用的是= 而不是==。 bash 中内置的test/[ 命令可以识别任何一种形式,但= 是原始语法,有些实现无法识别==

[ 是与if 一起使用的最常用命令,但您可以使用任何命令,包括 `grep:

if grep -q "lalala" mytest.txt; then SOME COMMANDS; fi

括号是不必要的。 (如果添加它们,您使用的是复合命令而不是简单命令;没有必要这样做。)

有关详细信息,请参阅 bash 手册 (info bash)。搜索

`test'

(带有反引号和撇号)了解有关内置 test 命令的信息。

Bash 还有一个[[ 命令,它比旧的[ 有一些优势。

【讨论】:

  • 非常感谢基思!你的回答很明确!如果您没有指出,就永远不会将 [ 作为命令!顺便说一句,您介意在 shell 中对双引号的使用进行一点评论吗?谢谢!
  • @CrazyFrog,关于引号——总是引用 all 扩展名,除非您有特定且令人信服的理由不这样做。请参阅mywiki.wooledge.org/Quotesmywiki.wooledge.org/Argumentswiki.bash-hackers.org/syntax/words
  • @CrazyFrog:还有一个变化:使用= 比使用==[test 更安全。 Bash 可以识别两者,但 = 是原始语法,一些 [test 实现无法识别 ==
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多