因此,作为 GIT 新手,因此对 bash 命令和脚本非常生疏,我一直在寻找不同的语法和脚本帮助。现在,我找到了很多帮助,并且能够创建脚本和别名,这将使我的 Git 体验更加愉快。
然而,我遇到了一些似乎让我困惑的细微差别,特别是与“if”命令相关的细微差别。
if [ -z $1 ] ; #<- Zero length string
if [[ -z $1 ]] ; #<- Also Zero Length String
if [[ "$1" == -* ]] ; #<- Starts with - (hyphen)
if [ -z $1 ] && [ -z $2 ] ; #<- both param 1 & 2 are zero length
if [[ -z $1 ]] && [[ -z $2 ]] ; #<- Also both param 1 & 2 are zero length
if [[ "$1" == -* ]] || [[ "$2" == -* ]] ; #<- Either param 1 or 2 starts with -
if [ "$1" == -* ] || [ "$2" == -* ] ; #<- Syntax Failure, "bash: ]: too many arguments"
为什么会出现差异?如何知道何时需要 [[(双精度)以及何时需要 [(单精度)?
感谢 Jaeden“Sifo Dyas”al'Raec Ruiner
答案1
首先,请注意,这两种类型的括号都不是 语法的一部分
if
。反而:
[
是内置 shell 的另一个名称test
;[[ ... ]]
是一个单独的内置函数,具有不同的语法和语义。
以下是 bash 文档的摘录:
[
/test
test: test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
-a FILE True if file exists.
(...)
[[ ... ]]
[[ ... ]]: [[ expression ]]
Execute conditional command.
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators:
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
EXPR1 && EXPR2 True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2 True if either EXPR1 or EXPR2 is true; else false
When the `==' and `!=' operators are used, the string to the right of
the operator is used as a pattern and pattern matching is performed.
When the `=~' operator is used, the string to the right of the operator
is matched as a regular expression.
The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
determine the expression's value.
Exit Status:
0 or 1 depending on value of EXPRESSION.
更简单地说,[
需要对 bash 表达式进行正常的处理,引用以避免插值等。因此,测试是否为$foo
空字符串或未设置的正确方法是:
[ -z "$foo" ]
或者
[[ -z $foo ]]
在第一种情况下引用很重要,因为设置foo="a b"
然后测试[ -z $foo ]
将导致test -z
接收两个参数,这是不正确的。
的语言[[ .. ]]
是不同的,并且正确地了解变量,这与人们对比 bash 更高级的语言所期望的方式非常相似。因此,它比经典[
/更不容易出错test
。
答案2
请键入man bash
并阅读文档。
你会在那里找到的东西:
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
The if list is executed. If its exit status is zero, the
then list is executed. Otherwise, each elif list is executed
in turn, and if its exit status is zero, the corresponding
then list is executed and the command completes. Otherwise,
the else list is executed, if present. The exit status is
the exit status of the last command executed, or zero if no
condition tested true.
这意味着之后if
可以有任何命令,并且 bash 只关心该命令的返回值。您在上面使用了两个不同的命令:[
和[[
。
test expr
[ expr ]
Return a status of 0 (true) or 1 (false) depending on the
evaluation of the conditional expression expr. Each operator
and operand must be a separate argument. Expressions are
composed of the primaries described above under CONDITIONAL
EXPRESSIONS. test does not accept any options, nor does it
accept and ignore an argument of -- as signifying the end of
options. [...]
这是许多 shell 上可用的经典测试。
[[ expression ]]
Return a status of 0 or 1 depending on the evaluation of the
conditional expression expression. Expressions are composed
of the primaries described below under CONDITIONAL EXPRES‐
SIONS. Word splitting and pathname expansion are not per‐
formed on the words between the [[ and ]]; tilde expansion,
parameter and variable expansion, arithmetic expansion, com‐
mand substitution, process substitution, and quote removal
are performed. Conditional operators such as -f must be
unquoted to be recognized as primaries.
When used with [[, the < and > operators sort lexicographi‐
cally using the current locale.
When the == and != operators are used, the string to the
right of the operator is considered a pattern and matched
according to the rules described below under Pattern Match‐
ing, as if the extglob shell option were enabled. The =
operator is equivalent to ==. If the shell option nocase‐
match is enabled, the match is performed without regard to
the case of alphabetic characters. The return value is 0 if
the string matches (==) or does not match (!=) the pattern,
and 1 otherwise. Any part of the pattern may be quoted to
force the quoted portion to be matched as a string.
这是 bash 的扩展,含义略有不同。尤其==
是定义不同。第一个进行字面比较,而第二个剂量通配符匹配。
答案3
当有疑问时(在 bash 中),总是使用双大括号 ( [[ ]]
),因为它们是单大括号的超集,在调用时更容易出现用户错误。
[
是 bash 中的内部命令,但在其他环境中可以是/bin/test
; 的符号链接。相应的]
实际上被忽略了,是为了美观而存在的。 归根结底,if /bin/test -z "$VAR"
和是相同的语句(尽管可能会也可能不会以 的名称调用子流程,具体取决于您的环境)。if [ -z "$VAR" ]
[
/bin/test
[[ ]]
也是 bash 的内在主义,所以没有子 shell,是 的超集[ ]
,并且还允许更友好的编写,它只是“做正确的事”,[ ]
会爆炸。
http://mywiki.wooledge.org/BashFAQ/031进入一个很多更多详情。