Simple Shell

Table of Contents

第一个 shell 脚本

1: #!/bin/sh
2: echo "Hello World!"

变量

 1: # 定义变量
 2: dec_var="declare variable"
 3: 
 4: # 使用变量
 5: echo $dec_var                   # → declare variable
 6: echo ${dec_var}                 # → declare variable
 7: 
 8: # 只读变量
 9: ro_var="readonly variable"
10: readonly ro_var
11: ro_var="re declare variable"    # → /bin/sh: Name: This variable is read only.
12: 
13: # 删除变量
14: del_var="delete variable"
15: unset del_var
16: echo $del_var                   # 没有任何输出

字符串

 1: u_name="Jack"
 2: echo "hello, ${u_name}!"        # → hello, Jack!
 3: 
 4: # 单引号里的任何字符都会原样输出
 5: echo 'hello, ${u_name}!'        # → hello, ${u_name}!
 6: 
 7: # 拼接字符串
 8: echo "hello, "$u_name"!"        # → hello, Jack!
 9: echo "hello, ${u_name}!"        # → hello, Jack!
10: 
11: echo 'hello, '$u_name'!'        # → hello, Jack!
12: echo 'hello, ${u_name}!'        # → hello, ${u_name}!
13: 
14: # 获取字符串长度
15: echo ${#u_name}                 # → 4
16: 
17: # 提取子字符串
18: echo ${u_name:1:3}              # → ack - 从 3 开始截取 3 个字符
19: 
20: # 查找子字符串
21: echo `expr index "$u_name" ck`  # → 2 - 字符 c 或 k 先出现的位置

数组

 1: # 定义数组
 2: # arr_name=(val1 val2 ... valN)
 3: arr_one_name=(0 1 2 3 4 5)
 4: 
 5: arr_two_name[0]="val0"
 6: arr_two_name[1]="val1"
 7: arr_two_name[n]="valN"
 8: 
 9: # 读取数组
10: echo ${arr_two_name[n]}         # → valN
11: # 使用 @ 或 * 符号获取数组中的所有元素
12: echo ${arr_two_name[@]}         # → val0 val1 valN
13: 
14: # 获取数组长度
15: echo ${#arr_one_name[@]}        # → 6
16: echo ${#arr_one_name[*]}        # → 6

注释

 1: # 这是一个单行注释
 2: # ---------------------------------
 3: # 多行注释
 4: 
 5: :<<EOF
 6: 注释内容...
 7: 注释内容...
 8: 注释内容...
 9: EOF
10: 
11: # OR 其他符号
12: 
13: :<<!
14: 注释内容...
15: 注释内容...
16: 注释内容...
17: !

脚本传参

 1: # !/bin/sh
 2: # test.sh
 3: echo "执行的文件名: $0";
 4: echo "第一个参数为: $1";
 5: echo "第一个参数为: $2";
 6: echo "第一个参数为: $3";
 7: 
 8: # 执行
 9: # chomod +x test.sh
10: # ./test.sh 1 2 3
11: # 结果如下 ↓↓↓
12: # ---------------------------------
13: # 执行的文件名: ./test.sh
14: # 第一个参数为: 1
15: # 第一个参数为: 2
16: # 第一个参数为: 3
17: # ---------------------------------

基本运算

 1: # 1. 算术运算符 + - * / % = == !=
 2: # 原生 bash 不支持简单的数字运算,需要通过其他命令来实现,如 awk 或 expr
 3: # 表达式要被 `` 包含
 4: # 表达式和运算符之间必须有空格,否则报错(Hmm...)
 5: echo `expr 1 + 1`               # → 2
 6: echo `expr 2 * 3`               # → 6
 7: 
 8: # 2. 关系运算符 -eq -ne -gt -lt -ge -le
 9: # 注意关系运算符只支持数字,不支持字符串
10: a=10
11: b=20
12: if [ $a -eq $b ]
13: then
14:     echo "a 等于 b"
15: else
16:     echo "a 不等于 b"
17: fi
18: 
19: # 3. 布尔运算符 ! -o -a
20: # 4. 逻辑运算符 && ||
21: # 5. 字符串运算符
22: # ---------------------------------
23: # = !=
24: # -z 检测字符串是否为 0 ,为 0 返回 true
25: # -n 检测字符串是否不为 0 ,不为 0 返回 true
26: # $  检测字符串是否为空,不为空返回 true
27: # ---------------------------------
28: 
29: # 6. 文件测试运算符
30: # 文件测试运算符用于检测 Unix 文件的各种属性,部分如下:
31: # -d file 检测是否是目录,是,返回 true
32: # -f file 检测文件是否为普通文件,是,返回 true
33: # -r file 检测文件是否为可读,是,返回 true
34: # -w file 检测文件是否为可写,是,返回 true
35: # -x file 检测文件是否为可执行,是,返回 true
36: # -s file 检测文件是否为空,不为空返回 true
37: # -e file 检测文件(包括目录)是否存在,是,返回 true

流程控制

条件

 1: # sh 的流程控制不可为空
 2: # 如果 else 分支没有语句执行,就不要写这个 else
 3: # 1. if
 4: if condition1
 5: then
 6:     command1
 7: fi
 8: # or 写成一行
 9: if condition1; then command1; fi
10: 
11: # 2. if else
12: if condition1
13: then
14:     command1
15: else
16:     command2
17: fi
18: 
19: # 3. if elif else
20: if condition1
21: then
22:     command1
23: elif condition2
24: then
25:     command2
26: else
27:     commandN
28: fi

循环

1. for 循环

1: for var in item1 item2 ... itemN
2: do
3:     command1
4:     command2
5:     ...
6:     commandN
7: done
8: # 
9: for var in item1 item2 ... itemN; do command1; command2… done;

2. while 语句

1: while condition
2: do
3:     command
4: done

3. until 语句

1: # 当 condition 为 false 时才执行
2: until condition
3: do
4:     command
5: done

4. case 语句

 1: case in
 2: 模式1)
 3:     command1
 4:     command2
 5:     command3
 6:     ;;
 7: 模式2
 8:     command1
 9:     command2
10:     command3
11:     ;;
12: *)
13:     command1
14:     command2
15:     command3
16:     ;;
17: esac

来看个例子:

 1: #!/bin/sh
 2: 
 3: site="runoob"
 4: 
 5: case "$site" in
 6:    "runoob") echo "菜鸟教程"
 7:    ;;
 8:    "google") echo "Google 搜索"
 9:    ;;
10:    "taobao") echo "淘宝网"
11:    ;;
12: esac
13: 
14: # → "菜鸟教程"

函数

函数定义格式:

[ function ] funname [()]{
    action;
    [return int;]
}
1: demoFun(){
2:     echo "This is a function."
3: }
4: 
5: demoFun                         # → This is a function.

函数传参:

 1: funWithParam(){
 2:     echo "第一个参数为 $1 !"
 3:     echo "第二个参数为 $2 !"
 4:     echo "第十个参数为 $10 !"
 5:     echo "第十个参数为 ${10} !"
 6:     echo "第十一个参数为 ${11} !"
 7:     echo "参数总数为 $#  个!"
 8:     echo "作为一个字符串输出所有参数 $* !"
 9: }
10: 
11: funWithParam 1 2 3 4 5 6 7 8 9 34 73
12: 
13: # 输出结果 ↓↓↓
14: # ---------------------------------
15: # 第一个参数为 1 !
16: # 第二个参数为 2 !
17: # 第十个参数为 10 ! --> 当n>=10时,需要使用${n}来获取参数
18: # 第十个参数为 34 !
19: # 第十一个参数为 73 !
20: # 参数总数有 11 个!
21: # 作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
22: # ---------------------------------

输入/输出重定向

command > file                  # 输出重定向
command >> file                 # 输出追加重定向

command < file                  # 输入重定向

n > file                        # 将文件描述符为 n 的文件重定向到 file
n >> file                       # 追加

n >& m                          # 将输出文件 m 和 n 合并
n <& m                          # 将输入文件 m 和 n 合并

文件包含

语法格式如下:

. filename                      # 注意点号(.) 和文件名中间有一空格
# 或
source filename

注:被包含的文件 test1.sh 不需要可执行权限。

Date: 2020-05-15 Fri 22:46

Author: Jack Liu

Created: 2020-05-16 Sat 03:48

Validate