shell脚本使用总结

原文链接:shell脚本使用总结
发布时间:2018-12-09 15:42:05

指定解释器

1
2
#!/bin/bash
## 这行代码必须加入文件头

定义或者赋值变量

因为shell是一个脚本语言,只有赋值了,才能成为一个变量,不像其他静态语言可以声明定义一个变量,其实就是赋值,变量必须赋值,才能成为变量,然后才能使用。修改变量,也是赋值。

注意,等号两边不能有空格

1
2
3
4
5
6
7
8
num=123
name="Kent"

## 也可以通过其他命令赋值,pwd两边的是反单引号,也称重音符,ascii是96
path=`pwd`

## 这里对num再次赋值,其实就是修改变量
num=456

使用变量

1
2
3
4
5
6
echo $num
echo $name
echo $path

## 加上大括号,是为了确定变量的边界
echo "my name is ${name}Zhang"

特殊变量

变量含义$0当前脚本的文件名$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。$#传递给脚本或函数的参数个数。$传递给脚本或函数的所有参数。$@传递给脚本或函数的所有参数。被双引号(“ “)包含时,与 $ 稍有不同,下面将会讲到。$?上个命令的退出状态,或函数的返回值。$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

字符串操作

0、 单引号和双引号

对于定义字符串,双引号和单引号都可以。但是单引号有如下的问题:

单引号会原样输出内容,忽略里面的变量和转义符号。

1
echo 'my name is ${name}Zhang\n'

输出:
my name is ${name}Zhang\n

1、拼接

1
2
3
4
5
6
7
8
fname="Kent"
sname="Zhang"

fullname="${fname}${sname}"
echo $fullname

fullname="${fname}Zhang"
echo $fullname

2、获取字符串长度

1
2
len=${#fullname}
echo $len

3、截取切片

1
2
fisrtname=${fullname:0:4} ## 表示从fullname,0位置开始,到4位置结束截取这部分字符串,不包含4的位置。
echo $firstname

4、查找子串

这个好像只能查找 单个字符,不能查找字符串,输出0表示查不到,输出1表示第1个字符。

1
echo `expr index "$fullname" K`

输出:
1

5、字符串替换

1
2
3
4
5
6
str="apple, tree, apple tree apple"
echo ${str/apple/APPLE} # 替换第一次出现的apple
echo ${str//apple/APPLE} # 替换所有apple

echo ${str/#apple/APPLE} # 如果字符串str以apple开头,则用APPLE替换它
echo ${str/%apple/APPLE} # 如果字符串str以apple结尾,则用APPLE替换它

逻辑判断

关于[[ ]]和[ ]判断判断表达式,尽量使用前者,因为前者更加通用,后者在特殊情况有可能无法正确执行。有关参考:

https://blog.csdn.net/taiyang1987912/article/details/39551385

一般形式

1
2
3
4
5
if [[ "$1" == "stop" ]]; then ## $1 表示第一个参数
exit 0
else
echo "go to here"
fi

多个逻辑分支

1
2
3
4
5
6
7
if [[ "$1" == "stop" ]]; then ## $1 表示第一个参数
echo 0
else [[ "$1" == "start" ]]; then
echo 1
else
echo "go to here"
fi

字符串比较

1
2
3
4
5
str1 = str2      ## 当两个串有相同内容、长度时为真
str1 != str2      ## 当串str1和str2不等时为真
-n str1        ## 当串的长度大于0时为真(串非空)
-z str1        ## 当串的长度为0时为真(空串)
str1         ## 当串str1为非空时为真

数字比较

1
2
3
4
5
6
int1 -eq int2    ## 两数相等为真
int1 -ne int2    ## 两数不等为真
int1 -gt int2    ## int1大于int2为真
int1 -ge int2    ## int1大于等于int2为真
int1 -lt int2    ## int1小于int2为真
int1 -le int2    ## int1小于等于int2为真

文件判断

1
2
3
4
5
6
7
8
9
-r file     ## 用户可读为真
-w file     ## 用户可写为真
-x file     ## 用户可执行为真
-f file     ## 文件为正规文件为真
-d file     ## 文件为目录为真
-c file     ## 文件为字符特殊文件为真
-b file     ## 文件为块特殊文件为真
-s file     ## 文件大小非0时为真
-t file     ## 当文件描述符(默认为1)指定的设备为终端时为真

包含文件

c++中,可以包含一个头文件,调用其他文件中的函数,shell同样可以,达到复用代码的效果,相当于把别的文件包含到了本文件中,其中变量函数都可以直接使用。

两种方式:

1、. filename //英文句号,后面一个空格

2、source filename

数组

定义

1
2
3
4
5
6
7
8
array1=(value0 value1 value2 value3)

array2=(
value0
value1
value2
value3
)

修改

1
2
array1[0]="1000"
array1[1]="1001"

使用

1
num=${array1[0]}

获取长度

1
2
# 取得数组元素的个数
length=${#array1[@]}

函数

定义函数,也可以去掉function关键字

1
2
3
4
5
6
7
8
9
10
11
function Sum()
{
## 注意,这里$1 $2表示函数传进来的参数
return $(($1+$2))
}

## 调用函数 传入2个参数
Sum 2 3

## 获取函数返回值,注意这里只能通过 $?获取返回值
echo $?

switch 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case "$1" in
start)
echo "start_service"
;;
stop)
echo "stop_service"
;;
restart)
echo "restart_service"
;;
*)
echo "unknown argument $1"
echo "usage:$0 [start|stop|restart|start_mock|stop_mock|restart_mock]"
esac

循环

for

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
#!/bin/sh
for i in 1 2 3 4 5 ## 遍历数字列表
do
echo "Looping ... number $i"
done

for i in hello 1 44 2 goodbye ## 遍历字符串列表
do
echo "Looping ... i is set to $i"
done

for file in $(ls) ## 通过shell命令获取一个列表
do
echo $file
done

for (( c=1; c<=5; c++ )) ## 类似C风格的循环
do
echo "c=$c"
done

array=(1 4 6 9 10) ## 遍历数组
for i in ${array[@]}
do
echo "array number $i"
done

while

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
n=1
while [ $n -le 10 ] ## n小于10就执行循环
do
echo $n
let n++ #或者写作n=$(( $n + 1 ))
done

## 冒号表示死循环
while :
do
echo I love you forever
done

## true命令永远是true,也是死循环
while /bin/true
do
echo I love you forever
done

until

until与while相反,until是当条件为false就继续循环,为true就结束循环。

1
2
3
4
5
6
7
8
#!/bin/bash
a=0

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

后续

未完待续…