1
2
3
4
// test.sh
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
#!/bin/bash
echo "hello world"
1
2
3
4
5
6
7
运行Shell脚本的方法
1 作为可执行程序
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本

2 作为解释器参数
/bin/sh test.sh

Shell变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#定义变量
my_name="foo"

#使用变量 只需要在变量名前加上 $ 符号
echo $my_name
#加花括号视为了帮助解释器识别变量的边界
echo ${my_name}

for skill in Java Coffee; do
echo "I am good at ${skill}Script"
done

#使用readonly将变量设为只读变量
my_name="foo"
readonly my_name #如果尝试修改变量值,会报错
my_name="bar" #my_name: readonly variable

#删除变量
#变量被删除后不能再次使用。unset 命令不能删除只读变量。
unset my_name
echo my_name #将没有任何输出

shell变量类型 三种

  1. 局部变量

局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量

  1. 环境变量

所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

  1. shell变量

    shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    shell字符串

    字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。

    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
     your_name="foo"
    # 使用双引号拼接
    greeting="hello, "$your_name" !"
    greeting_1="hello, ${your_name} !"
    echo $greeting $greeting_1
    # 使用单引号拼接
    greeting_2='hello, '$your_name' !'
    greeting_3='hello, ${your_name} !'
    echo $greeting_2 $greeting_3

    输出
    hello, foo ! hello, foo !
    hello, foo ! hello, ${your_name} !

    #获取字符串的长度
    str="abcd"
    echo ${#str} #输出 4

    #提取子串
    #以下实例从字符串第 2 个字符开始截取 4 个字符
    str="hello world"
    echo ${str:1:4} $输出 ello

    #查找子字符串的位置
    #查找字符 l 或 o 的位置(哪个字母先出现就计算哪个):
    string="hello world"
    echo `expr index "$string" lo` # 输出 2

shell 数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#数组 数组名=(值1 值2 ... 值n)
arr=(
v1
v2
v3
)
echo "数组 ${arr[1]}"
#使用 @ 符号可以获取数组中的所有元素
echo “数组中的所有元素 ${arr[@]}”
#获取数组的长度
echo "数组的长度 ${#arr[@]}"
#或者
echo "数组的长度 ${#arr[*]}"
#获取数组单个元素的长度
echo "数组第二个元素的长度 ${#arr[1]}"

#还可以单独定义数组的各个分量:

array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

shell传递参数

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# $ ./test.sh 1 222 3 4

#!/bin/bash
echo "shell 传递参数实例"
echo "执行的文件名 $0"
echo "第一个参数 $1"
echo "第二个参数 $2"
echo "第三个参数 $3"
echo "参数个数 $#"
echo "所有参数 $*"
echo "所有参数 加引号 \"$@\""
echo "脚本当前进程ID $$"
echo "后台运行的最后一个进程的ID $!"
echo "shell使用的当前选项 $-"

echo "-- \$* 演示--"
for i in "$*"; do
echo $i
done

echo "-- \$@ 演示--"
for i in "$@"; do
echo $i
done

#输出
shell 传递参数实例
执行的文件名 ./test.sh
第一个参数 1
第二个参数 222
第三个参数 3
参数个数 4
所有参数 1 222 3 4
所有参数 加引号 "1 222 3 4"
脚本当前进程ID 20530
后台运行的最后一个进程的ID
shell使用的当前选项 hB
-- $* 演示--
1 222 3 4
-- $@ 演示--
1
222
3
4

shell算数运算

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash

a=10
b=20
echo "a $a, b $b"

#加法
val=`expr $a + $b`
echo "a + b: $val"

#乘法 需要转义
val=`expr $a \* $b`
echo "a * b: $val"

#除法
val=`expr $b / $a`
echo "b / a: $val"

#取余
val=`expr $a % $b`
echo "a % b: $val"

if [ $a == $b ]
then
echo "a 等于 b"
fi

if [ $a != $b ]
then
echo "a 不等于 b"
fi

#输出
a 10, b 20
a + b: 30
a * b: 200
b / a: 2
a % b: 10
a 不等于 b


#扩展 三种加法运算写法
a=10
b=20

c=`expr $a + $b`

echo "c: $c"

d=$[ `expr $a + $b` ]
echo "d: $d"

e=$[ 10 + 20 ]
echo "e: $e"

shell 关系运算符

假设变量a=10 b=20

运算符 说明 用法示例
-eq 检测两个数是否相等 [ $a -eq $b ] 返回 false
-nq 检测两个数是否不相等 [ $a -nq $b]
-gt >
-lg <
-ge >=
-le <=

布尔运算符

运算符 说明 用法
! 非运算 [ !false ] 返回true
-o 或运算 [ $a -lt 20 -o $b -gt 100]
-a 与运算

逻辑运算符

运算符 说明 用法
&& 逻辑AND [[ $a -lt 100 && $b -gt 100 ]]
` `
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

a=10
b=20

if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "true"
else
echo "false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "true"
else
echo "false"
fi

字符串运算符

假设变量a=”abc” b=”efg”

运算符 说明 举例
= 检测两个字符串是否相等 [ $a =$b ]返回false
!=
-z 检测字符串长度是否为0,为0返回true [ -z $a ] false
-n 检测字符串长度是否不为0 [ -n “$a” ] true
str 检测字符串是否为空,不为空返回true [ $a ] true
1
2
3
4
5
tips


使用 [[ ... ]] 条件判断结构,而不是 [ ... ],能够防止脚本中的许多逻辑错误。
比如,&&、||、< 和 > 操作符能够正常存在于 [[ ]] 条件判断结构中,但是如果出现在 [ ] 结构中的话,会报错。

printf输出

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
printf 命令模仿 C 程序库(library)里的 printf() 程序。

printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。

printf 命令的语法:

printf format-string [arguments...]
参数说明:

format-string: 为格式控制字符串
arguments: 为参数列表。

#!/bin/bash


printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"

# 没有引号也可以输出
printf %s abcdef

# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def

printf "%s\n" abc def

printf "%s %s %s\n" a b c d e f g h i j

# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n"

#输出
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j
and 0

shell流程控制

if 条件

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

a=10
b=20

if test $a -lt $b; then
printf '%s\n' "a < b"
elif [[ $a -gt $b ]]; then
echo "a > b"
fi

for 循环

1
2
3
4
5
6
7
8
9
10
for a in 1 2 3 4 5; do
echo $a #不要忘了变量前加 $
done

#第二种写法,类似于C语言写法

#!/bin/bash
for((i=1;i<=5;i++));do
echo "这是第 $i 次调用"
done;

while 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while condition
do
command
done


#!/bin/bash

i=1
while(( $i<5 ))
do
echo $i
i=`expr $i + 1`
done

until 语句

1
2
3
4
5
6
7
8
9
#!/bin/bash

a=0

until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done

case 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
case的语法和C family语言差别很大
它需要一个esac(就是case反过来)作为结束标记
每个case分支用右圆括号,用两个分号表示break。


#!/bin/bash
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in #变量后面必须跟上 in
1) echo '你选择了 1' #每一个模式必须以右括号结束
;; #相当于break;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
# * 相当于 default
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac #结束case

跳出循环

1
2
break
continue

函数

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
31
32
33
34
35
36
37
38
39
#!/bin/bash
#定义函数
demoFun(){
echo "第一个shell函数"
}

#执行函数
demoFun


###带返回值的函数
funcWithReturn () {
echo "输入a"
read a
echo "输入b"
read b

echo -e "a + b = \c"
return $(($a + $b))
}
#执行函数
funcWithReturn
#通过 $?获取函数执行后的返回值
echo "$?"


###给函数传参
funWithParam () {
echo $@
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
i=1
for arg in $@; do
echo "第${i}个参数为 $arg"
i=$(($i+1))
done
}

funWithParam 1 2 3 4 5