这个小技巧来自 Youtube 上的个视频,很受用所以记录下。很多时候我们写的 Shell 脚本,都会前置些判断条件,以便正确执行想要的结果,例如:

if [ -x $(which vim) ]; then
    export EDITOR="vim"
fi

这样子写当然没有任何的问题,而且看起来就很直观。但是如果吹毛求疵的话,发现这样子的判断有点繁琐,同时会在写更复杂的 Shell 的时候,会增加更多的判断,这样子会造成整个 Shell 脚本非常的繁琐以及臃肿。

例如,我们可以阅读 neofetch 的源代码,这个脚本用于探测目标系统未知的情况下,获取对应的值,因此其会有非常多的条件判断。

BASH Script

这个例子可能会比较极端,那问题凸显得很明显。那么这种情况下,如何去优化自己的 Shell 代码呢?

首先我们要从返回值说起,我们都知道我们执行的每条 Shell 语句其实都有返回值。一般来说,返回 0 表示正常,返回非 0 表示这条语句可能会有问题。

我们如下做个尝试:

BASH Script

然后,通常我们写的条件判断,其实就是根据返回值的判断这个条件是否成立,下面是我们常见的「与、或、非」的判断:

BASH Script

那么其实我们可以知道当不同的逻辑判断,它们执行的顺序是不一样的。例如,我们需要「与」判断则需要将所有的条件语句都运行完毕,而「或」判断则只需要其中的一条语句满足条件即可(「非」也是类似)。

那么作为条件判断的例子,可以直接写为:

BASH Script

然后,我们将上面的代码结合起来,我们可以写成这个样子:

[ -x $(which vim) ] && export EDITOR="vim"

因为它们之间的条件其实是「与」的关系。然后,我们再多些例子看看这样子的写法是不是对应的精简了很多:

if [ ! -x $(which vim ) ]; then
  exit -1
fi

对比

[ -x $(which vim ) ] || exit -1 # 注意这里的「非」的用法

如果是多条语句,那么可以使用代码块的方式(在 Shell 里面其实就是个函数):

[ -x $(which vim ) ] && {
  export EDITOR="vim"
  echo "vim is installed"
}

既然引入了代码块,那么我们可以用更复杂的用法了,例如可以将两个代码块(函数)结合起来,这样子就可以写出非常短小精悍的条件判断:

{ cmd not found } || { echo "prev statment return value is \$?" }

看起来稍微有点复杂,但又带来了更多的内容:

  1. 你可以将两个代码块(函数)使用逻辑操作符链接起来;
  2. 后面的代码块可以接收前面代码块最后一条语句的返回值。

总体来说,这个小技巧可以精简不少的条件判断的代码,尤其在初始化的时候看起来非常的直观。

不过和很多的技巧一样,我们还是需要酌情的使用它,毕竟代码和脚本的可读性是放在第一位的。

- eof -