学习地址

运行

需要在shell文件头部指定使用哪种解析器解析当前文件

1
#!/bin/bash

shell文件添加可执行权限才可以执行

1
chmod +x shell文件名

运行shell脚本

1
2
3
./shell.sh

bash shell.sh

注释

1
2
3
4
5
6
7
8
# 单行注释使用 '#' 号,也可用于多行注释

# 多行注释
:<<EOF
注释内容...
注释内容...
注释内容...
EOF

变量

注意

  1. 定义变量时,=号两侧不能有空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义变量
first_var='css'
second_var='marry'
third_var='cui'

# 使用变量
echo ${first_var}

# 已经定义的变量可以重新被定义
first_var='cui'

# 只读变量
readonly first_var

# 删除变量,不能删除只读变量
unset first_var

变量分为局部变量、环境变量、shell 变量

  1. 局部变量 局部变量在脚本或命令中定义,仅在当前 shell 实例中有效,其他 shell 启动的程序不能访问局部变量。
  2. 环境变量 所有的程序,包括 shell 启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候 shell 脚本也可以定义环境变量。
  3. shell 变量 shell 变量是由 shell 程序设置的特殊变量。shell 变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了 shell 的正常运行

字符串

注意

  1. 单引号内不能使用变量转义符号,双引号可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义变量
username="曹少帅"
introduction="I am ${username}"

echo $introduction

# 获取字符串长度,变量前加#号
echo "我的名字有${#username}个字符"

# 截取字符串,截取第0位到第1位
echo "我的姓氏是${username:0:1}"

# 查找子字符串
echo `expr index "${username}" 帅`

# 输出带转义符号的字符串,需要加上-e参数
echo -e "\n\n"

数组

只支持一维数组,值通过空格隔开,不限定大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 定义数组
arr=(1 2 3 4 5)

# 读取数组
echo "数组第一位的值是${arr[0]}"

# 使用@符号获取数组所有元素
echo "数组的全部元素是${arr[@]}"

# 获取数组长度
echo "数组的长度为${#arr[@]}"
echo "数组的长度为${#arr[*]}"

# 获取单个元素的长度
echo "数组第一个元素的长度为${#arr[0]}"

传递参数

使用$n来获取第 n 个参数,n 是从 0 开始的数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
./shell.sh 1 2 3

echo "参数个数:$#" # 3

echo "返回一个包含所有参数的字符串,用空格分开:$*" # '1 2 3'

echo "脚本运行的进程id号:$$" # xxx

echo "将每一个参数用字符串进行包裹:$@" # '1' '2' '3'

# 使用$*
for i in "$*";
do echo $i
done
# 输出 1 2 3

# 使用所有参数 $@
for j in "$@";
do echo $j
done
# 输出
# 1
# 2
# 3

运算符

注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 `` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
  • 注意中括号和参数之间也要有空格,否则报错

算术运算符

使用expr关键字来实现算术运算,值与运算符之间要有空格

1
2
3
4
5
6
7
8
9
10
11
12
a=2
b=3

val=`expr $a + $b`
echo "a + b = $val"

# 乘法前面需要加上\
val=`expr $a \* $b`
echo "a * b = $val"

val=`expr $a - $b`
echo "a - b = $val"

关系运算符

注意

  1. 注意中括号和参数之间也要有空格,否则报错
  2. 关系运算符只支持数字,不支持字符串,除非字符串的值是数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -eq(equal)等于 [a -eq b]
# -ne()不等于
# -gt(great than)大于
# -lt(less than)小于
# -ge(great equal)大于等于
# -le(less equal)小于等于

a=2
b=3

if [ $a -eq $b ]
then
echo "a等于b"
else
echo "a不等于b"
fi

if [ $a -lt $b ]
then
echo "a小于b"
else
echo "a大于b"
fi

布尔运算符

1
2
3
4
5
6
7
8
9
10
11
# !(非)
# -o(or)或
# -a(and)与

a=2
b=3

if [ $a -lt $b -o $a -gt $b ]
then
echo "a小于b或者a大于b"
fi

逻辑运算符

1
2
# &&逻辑AND
# ||逻辑OR

字符串运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# = 是否相等
# !=是否不等
# -z 长度是否为0
# -n长度是否不为0
# $ 是否不为空,不为空返回true

str1='123'
str2='456'
str3=''

if [ $str1 = $str2 ]
then
echo "str1等于str2"
else
echo "str1不等于str2"
fi

if [ -z $str3 ]
then
echo "str3长度为0"
else
echo "str3长度不为0"
fi

if [ $str3 ]
then
echo "str3不为空"
else
echo "str3为空"
fi

文件测试运算符(TODO)

输出函数

printf

1
2
3
4
5
6
# 根c语言的printf方法类似
# 写法:printf "字符串" 参数1 参数2 ...
# %s %d %f %c
# %-10s,-代表左对其,默认右对其

printf "%-10s" 姓名 # 输出限定为长度为10的字符串

控制语句

流程控制

1
2
3
4
5
6
7
8
9
# 配合test使用
# 控制语句的条件语句可以包括在双层小括号中(())

# 等价于 if test $[$1] == $[$2]
if (($1 == $2))
then
echo "true"
else
echo "false"

循环控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
for var in 1 2 3 4 5 6
do
echo $var
done

num=0
while (($num <= 5))
do
echo $num
let num++
done

num2=0
until (($num2>5))
do
echo $num2
let num2++
done
echo "结束"

# 相当于switch case *相当于default
read input
case $input in
1) echo "输入$input";;
2) echo "输入$input";;
*) echo "没有找到匹配项"
esac

break continue

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foo() {
# 函数内部使用$1 $2 $n来获取参数
return "123"
}
# 在函数执行的后面使用$?获取返回值
foo
echo "$?" # 123

# 例子
foo() {
return $1
}

# 调用函数
foo 1