bash 中 if [ ... 和 test ... 语句的区别

fuu*_*ind 2 bash test exit-status

考虑以下:

echo "hello" > file.txt
is_match1 () {
  local m
  m=$(cat "file.txt" | grep -F "$1")
  if [ -z "$m" ]; then
    return 1
  fi
}
is_match2 () {
  local m
  m=$(cat "file.txt" | grep -F "$1")
  test -z "$m" && return 1
}
is_match1 "hello"
echo "$?"
0
is_match2 "hello"
echo "$?"
1
Run Code Online (Sandbox Code Playgroud)

为什么is_match2返回1?

Kus*_*nda 6

根据您的问题的情况,获取两个函数的m值。hello

现在看看

test -z "$m" && return 1
Run Code Online (Sandbox Code Playgroud)

这里应该发生什么?测试-z结果是假的吧?所以return 1不执行。相反,该函数返回什么?$?每个函数最后都会返回 的值。在本例中,该值为 1,即列表的结果&&

您可能想测试的是

if [ -z "$m" ]; then return 1; fi
Run Code Online (Sandbox Code Playgroud)

相比

if test -z "$m"; then return 1; fi
Run Code Online (Sandbox Code Playgroud)

当为非空时,这两个语句的退出状态if均为零,因为没有采用任何语句的分支。$m

来自POSIX 标准

命令的退出状态应是已执行的或复合列表if的退出状态,如果没有执行,则为零。thenelse


请注意,我们可能会将您的两个功能压缩为

is_match () {
    grep -q -F -e "$1" file.txt
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们grep向调用者提供退出状态。我们也不一定会读完file.txt文件,因为grep -q一旦找到匹配项就会退出。