Logo
Section 1 / 13

if 语句

详细了解 if 语句的工作原理,以及一行代码写法和易出错的代码。

检查点

if 语句

详细了解 if 语句的工作原理,以及一行代码写法和易出错的代码。

条件语句

我们第一次接触到条件语句,是在学习 find 工具的时候。随后,我们了解到 Bash 自带了逻辑运算符 AND(&&)和 OR(||)。Bash 还提供了其他用于分支的选项。

if 和 case 这两个运算符在编写 Bash 脚本时被频繁使用。它们的行为相似,但各自更适合特定的任务。

if 语句

假设我们编写一条单行命令。这种命令被称为 一行命令(one-liner)。我们希望它尽可能紧凑,因为简短的命令输入更快。同时,代码越短,输入时出错的可能性就越小。

现在再假设我们编写一个脚本。脚本存储在硬盘上,我们定期调用它,很少修改它。此时代码的简洁性并不重要,相反,我们更希望代码易于阅读和修改。

&& 和 || 运算符非常适合一行命令。但在编写脚本时,Bash 提供了更好的选择。这取决于具体场景。有时在脚本中使用逻辑运算符也能保持代码清晰。然而,在大多数情况下,逻辑运算符会使代码难以阅读。因此,最好用 if 和 case 语句来替代它们。

下面是一个需要使用 if 语句的示例。让我们看看备份脚本中的这段 tar 命令:

1tar -cjf "$1".tar.bz2 "$@" && 2 echo "tar - OK" > results.txt || 3 { echo "tar - FAILS" > results.txt ; exit 1 ; }

编写这个脚本时,我们试图让代码更易读。这一动机促使我们将 tar 和 mv 的调用分开。但这种解决方案仍然不够理想。tar 命令太长且复杂,难以阅读。因此,在修改时很容易出错。这种容易出错的代码被称为 脆弱代码(fragile code)。当我们对问题采用不良的技术方案时,就会产生这类代码。

改进代码

让我们改进这段 tar 命令。提升代码质量的第一步是清晰地写出其算法。我们当前情况的算法如下:

  1. 从 $@ 变量中读取文件和目录列表。
  2. 对这些文件和目录进行归档和压缩。
  3. 如果归档成功,将“tar - OK”写入日志文件。
  4. 如果发生错误,将“tar - FAILS”写入日志文件并终止脚本。

最后一步是最令人困惑的。当 tar 成功时,脚本只执行一个动作;而当出错时,需要执行两个动作。这两个动作通过大括号组合成一个 命令块。这样的代码结构显得过于复杂。

if 语句根据特定条件执行命令块。其通用形式如下:

1if CONDITION 2then 3 ACTION 4fi

我们也可以将 if 语句写成一行。只需在 then 和 fi 前加上分号即可:

1if CONDITION; then ACTION; fi

这里的条件和动作可以是一个单独的命令,也可以是一组命令块。如果条件的退出状态为零,Bash 就会执行对应的动作。

下面是一个 if 语句的示例。点击“运行”按钮,观察 if-smt.sh 在两个不同文件夹中的执行结果。

名为 Same 的文件夹包含两个内容相同的文件,而 Different 文件夹中的文件内容不同。请观察该脚本在这两个文件夹中的输出结果。

No configuration found for ID: 239225fa6d3f35e5fb8b20328c28ba1fa17fd3588a871a3dfe4c086aa873bee0

cmp 工具

if_smt.sh 脚本调用了 cmp 工具。在这里,调用 cmp 作为条件。该工具用于比较两个文件的内容。如果文件内容不同,cmp 会输出第一个不同字符的位置;此时退出状态非零。如果两个文件内容相同,则返回零状态。

当我们把某个工具或命令放在 if 条件中时,只关心它的退出状态。因此,我们将 cmp 的输出重定向到 /dev/null。这是一个特殊系统文件,所有写入其中的数据都会被操作系统丢弃。该操作始终成功。

当 file1.txt 与 file2.txt 的内容相同时,cmp 工具返回零状态,此时 if 条件为真,echo 命令会打印相应消息。

Quiz

单选题

条件为真,当退出状态为哪个值时?

1 / 1

变量和参数

if-else 语句