# Shell 布尔运算

## 常规的布尔运算

### 在 Shell 下如何进行逻辑运算

#### 范例：true or false

``````\$ if true;then echo "YES"; else echo "NO"; fi
YES
\$ if false;then echo "YES"; else echo "NO"; fi
NO``````

#### 范例：与运算

``````\$ if true && true;then echo "YES"; else echo "NO"; fi
YES
\$ if true && false;then echo "YES"; else echo "NO"; fi
NO
\$ if false && false;then echo "YES"; else echo "NO"; fi
NO
\$ if false && true;then echo "YES"; else echo "NO"; fi
NO``````

#### 范例：或运算

``````\$ if true || true;then echo "YES"; else echo "NO"; fi
YES
\$ if true || false;then echo "YES"; else echo "NO"; fi
YES
\$ if false || true;then echo "YES"; else echo "NO"; fi
YES
\$ if false || false;then echo "YES"; else echo "NO"; fi
NO``````

#### 范例：非运算，即取反

``````\$ if ! false;then echo "YES"; else echo "NO"; fi
YES
\$ if ! true;then echo "YES"; else echo "NO"; fi
NO``````

### Bash 里头的 true 和 false 是我们通常认为的 1 和 0 么？

#### 范例：返回值 v.s. 逻辑值

`true``false` 它们本身并非逻辑值，它们都是 Shell 的内置命令，只是它们的返回值是一个“逻辑值”：

``````\$ true
\$ echo \$?
0
\$ false
\$ echo \$?
1``````

#### 范例：查看 true 和 false 帮助和类型

``````\$ help true false
true: true
Return a successful result.
false: false
Return an unsuccessful result.
\$ type true false
true is a shell builtin
false is a shell builtin``````

## 条件测试

### 条件测试基本使用

#### 范例：数值测试

``````\$ if test 5 -eq 5;then echo "YES"; else echo "NO"; fi
YES
\$ if test 5 -ne 5;then echo "YES"; else echo "NO"; fi
NO``````

#### 范例：字符串测试

``````\$ if test -n "not empty";then echo "YES"; else echo "NO"; fi
YES
\$ if test -z "not empty";then echo "YES"; else echo "NO"; fi
NO
\$ if test -z "";then echo "YES"; else echo "NO"; fi
YES
\$ if test -n "";then echo "YES"; else echo "NO"; fi
NO``````

#### 范例：文件测试

``````\$ if test -f /boot/System.map; then echo "YES"; else echo "NO"; fi
YES
\$ if test -d /boot/System.map; then echo "YES"; else echo "NO"; fi
NO``````

### 各种逻辑测试的组合

#### 范例：如果 a，b，c 都等于下面对应的值，那么打印 YES，通过 -a 进行"与"测试

``````\$ a=5;b=4;c=6;
\$ if test \$a -eq 5 -a \$b -eq 4 -a \$c -eq 6; then echo "YES"; else echo "NO"; fi
YES``````

#### 范例：测试某个“东西”是文件或者目录，通过 -o 进行“或”运算

``````\$ if test -f /etc/profile -o -d /etc/profile;then echo "YES"; else echo "NO"; fi
YES``````

#### 范例：测试某个“东西”是否为文件，测试 `!` 非运算

``````\$ if test ! -f /etc/profile; then echo "YES"; else echo "NO"; fi
NO``````

### 比较 -a 与 &&, -o 与 ||， ! test 与 test !

#### 范例：要求某文件可执行且有内容，用 -a 和 && 分别实现

``````\$ cat > test.sh
#!/bin/bash
echo "test"
[CTRL+D]  # 按下组合键CTRL与D结束cat输入，后同，不再注明
\$ chmod +x test.sh
\$ if test -s test.sh -a -x test.sh; then echo "YES"; else echo "NO"; fi
YES
\$ if test -s test.sh && test -x test.sh; then echo "YES"; else echo "NO"; fi
YES``````

#### 范例：要求某个字符串要么为空，要么和某个字符串相等

``````\$ str1="test"
\$ str2="test"
\$ if test -z "\$str2" -o "\$str2" == "\$str1"; then echo "YES"; else echo "NO"; fi
YES
\$ if test -z "\$str2" || test "\$str2" == "\$str1"; then echo "YES"; else echo "NO"; fi
YES``````

#### 范例：测试某个数字不满足指定的所有条件

``````\$ i=5
\$ if test ! \$i -lt 5 -a \$i -ne 6; then echo "YES"; else echo "NO"; fi
YES
\$ if ! test \$i -lt 5 -a \$i -eq 6; then echo "YES"; else echo "NO"; fi
YES``````

• 有时可以不用 `!` 运算符，比如 `-eq``-ne` 刚好相反，可用于测试两个数值是否相等； `-z``-n` 也是对应的，用来测试某个字符串是否为空
• `Bash` 里，`test` 命令可以用[] 运算符取代，但是需要注意，[`之后与`] 之前需要加上额外的空格
• 在测试字符串时，所有变量建议用双引号包含起来，以防止变量内容为空时出现仅有测试参数，没有测试内容的情况

• `-ne``-eq` 对应的，我们有时候可以免去 `!` 运算

``````\$ i=5
\$ if test \$i -eq 5; then echo "YES"; else echo "NO"; fi
YES
\$ if test \$i -ne 5; then echo "YES"; else echo "NO"; fi
NO
\$ if test ! \$i -eq 5; then echo "YES"; else echo "NO"; fi
NO``````
• `[ ]` 可以取代 `test`，这样看上去会“美观”很多

``````\$ if [ \$i -eq 5 ]; then echo "YES"; else echo "NO"; fi
YES
\$ if [ \$i -gt 4 ] && [ \$i -lt 6 ]; then echo "YES"; else echo "NO"; fi
YES``````
• 记得给一些字符串变量加上 `""`，记得 `[` 之后与 `]` 之前多加一个空格

``````\$ str=""
\$ if [ "\$str" = "test"]; then echo "YES"; else echo "NO"; fi
-bash: [: missing `]'
NO
\$ if [ \$str = "test" ]; then echo "YES"; else echo "NO"; fi
-bash: [: =: unary operator expected
NO
\$ if [ "\$str" = "test" ]; then echo "YES"; else echo "NO"; fi
NO``````

``````#include <stdio.h>
int main()
{
int i, j;

i=5;j=1;
if ((i==5) && (j=5))  printf("%d\n", j);

return 0;
}``````

## 命令列表

### 命令列表的执行规律

#### 范例：如果 ping 通 www.lzu.edu.cn，那么打印连通信息

``\$ ping -c 1 www.lzu.edu.cn -W 1 && echo "=======connected======="``

### 命令列表的作用

#### 范例：在脚本里判断程序的参数个数，和参数类型

``````#!/bin/bash

echo \$#
echo \$1
if [ \$# -eq 1 ] && (echo \$1 | grep ^[0-9]*\$ >/dev/null);then
echo "YES"
fi``````

``````#!/bin/bash

echo \$#
echo \$1
! ([ \$# -eq 1 ] && (echo \$1 | grep ^[0-9]*\$ >/dev/null)) && exit 1

echo "YES"``````