一、基本介绍
Shell Script是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与指令写在里面,然后用正规表示法,管道命令以及数据流重导向等功能,以达到我们所想要的处理目的。
二、Shell 脚本的创建
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 first.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
创建方法:终端输入 touch first.sh 或 vim first.sh 即可创建。
#!/bin/bash
echo "Hello World !"
三、运行 Shell 脚本的两种方法
1、作为可执行程序
将上面的代码保存为 first.sh,并 cd 到相应目录:
chmod +x ./first.sh #使脚本具有执行权限
./first.sh #执行脚本
2、作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:
sh first.sh
四、详细介绍
Shell 变量
1、变量名的命名须遵循如下规则:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)。
2、变量的使用:
使用一个定义过的变量,只要在变量名前面加美元符号即可,而且已定义的变量,可以被重新定义,例如:
your_name="tom"
echo $your_name
your_name="alibaba"
echo $your_name
3、变量类型:
运行shell时,会同时存在三种变量:
1) 局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
2) 环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
3) Shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。
Shell 字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。
1、单引号
str='this is a shell script'
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
2、双引号
your_name='tom'
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str
输出结果为:
Hello, I know you are "tom"!
双引号的优点:
- 双引号里可以有变量;
- 双引号里可以出现转义字符。
3、拼接字符串
your_name="tom"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
输出结果为:
hello, tom ! hello, tom !
4、获取字符串长度
string="nihao"
echo "nihao的长度为:${#string}"
输出结果为:
nihao的长度为:5
5、提取子字符串
以下实例从字符串第 2 个字符开始截取 6 个字符:
string="this is a shell script"
echo ${string:1:6}
输出结果为:
his is
Shell 数组
1、定义数组
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)。与大部分编程语言类似,数组元素的下标由0开始。
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
还可以单独定义数组的各个分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
2、读取数组
读取数组元素值的一般格式是:
value=${array_name[n]}
例如:
my_array=(A B "C" D)
echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"
输出结果为:
第一个元素为: A
第二个元素为: B
第三个元素为: C
第四个元素为: D
3、获取数组中的所有元素
使用 @ 符号可以获取数组中的所有元素,例如:
my_array=(A B "C" D)
echo "元素总数为: ${my_array[@]}"
echo "元素总数为: ${my_array[*]}"
输出结果为:
元素总数为: A B C D
元素总数为: A B C D
4、获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同:
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
例如:
my_array=(A B "C" D)
echo "元素个数为: ${#my_array[@]}"
echo "元素个数为: ${#my_array[*]}"
echo "第三个元素长度为: ${#my_array[2]}"
输出结果为:
元素个数为: 4
元素个数为: 4
第三个元素长度为: 1
Shell 注释
1、单行注释
以 # 开头的行就是注释,会被解释器忽略。
#echo "nihao"
2、多行注释
:<
EOF 也可以使用其他符号:
:<
Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:0 为执行的文件名。例如:
function passparam()
{
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
}
passparam a b c
输出结果为:
Shell 传递参数实例!
执行的文件名:first.sh
第一个参数为:a
第二个参数为:b
第三个参数为:c
备注:几个用来处理参数的特殊字符:
Shell echo命令
1、显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量。例如:
echo "输入你的姓名:"
read name
echo "my name is $name"
运行得到:
输入你的姓名:
输入内容:
输入你的姓名:
tom
得到结果:
输入你的姓名:
tom
my name is tom
Shell 基本运算符
Shell 和其他编程语言一样,支持多种运算符,包括:算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
注意:
1)表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2。
2)完整的表达式要被 ` `
包含,注意这个字符不是常用的单引号,在 Esc 键下边。
1、算术运算符
运算符 | 说明 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法(乘号前边必须加反斜杠才能实现乘法运算) |
/ | 除法 |
% | 取余 |
= | 赋值 |
== | 相等。用于比较两个数字,相同则返回 true。 |
!= | 不相等。用于比较两个数字,不相同则返回 true |
注意:条件表达式要放在方括号之间,并且要有空格,例如: [b] 是错误的,必须写成 [ b ]。
举例:
a=2
b=4
echo "a=2 b=4"
#加法
val=`expr $a + $b`
echo "a + b = $val"
val=`expr $a - $b`
echo "a - b = $val"
val=`expr $a \* $b`
echo "a * b = $val"
val=`expr $a / $b`
echo "a / b = $val"
val=`expr $b % $a`
echo "b % a = $val"
if [ $a == $b ]
then
echo "a 等于 b"
else
echo "a 不等于 b"
fi
if [ $a != $b ]
then
echo "a_ 不等于 b_"
else
echo "a_ 等于 b_"
fi
输出结果为:
a=2 b=4
a + b = 6
a - b = -2
a * b = 8
a / b = 0
b % a = 0
a 不等于 b
a_ 不等于 b_
2、关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 | 说明 |
---|---|
-eq | 检测两个数是否相等,相等返回 true。 |
-ne | 检测两个数是否不相等,不相等返回 true |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 |
举例:
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
输出结果为:
10 -eq 20: a 不等于 b
10 -ne 20: a 不等于 b
10 -gt 20: a 不大于 b
10 -lt 20: a 小于 b
10 -ge 20: a 小于 b
10 -le 20: a 小于或等于 b
3、布尔运算符
运算符 | 说明 |
---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 |
举例:
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
输出结果为:
10 != 20 : a 不等于 b
10 小于 100 且 20 大于 15 : 返回 true
10 小于 100 或 20 大于 100 : 返回 true
10 小于 5 或 20 大于 100 : 返回 false
4、逻辑运算符
举例:
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
输出结果为:
返回 false
返回 true
5、字符串运算符
运算符 | 说明 |
---|---|
= | 检测两个字符串是否相等,相等返回 true。 |
!= | 检测两个字符串是否相等,不相等返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true |
-n | 检测字符串长度是否为0,不为0返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 |
举例:
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
输出结果为:
abc = efg: a 不等于 b
abc != efg : a 不等于 b
-z abc : 字符串长度不为 0
-n abc : 字符串长度不为 0
abc : 字符串不为空
6、文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。
属性检测描述如下:
运算符 | 说明 |
---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 |
-r file | 检测文件是否可读,如果是,则返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 |
举例:
备注:file="/Users/wangxueqi/Desktop/first.sh"为存放在桌面的当前脚本。
file="/Users/wangxueqi/Desktop/first.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
输出结果为:
文件可读
文件可写
文件可执行
文件为普通文件
文件不是个目录
文件不为空
文件存
Shell 流程控制
和Java、PHP等语言不一样,sh的流程控制不可为空
1、if 语句语法格式:
if condition
then
command1
command2
...
commandN
fi
例如:
a=10
b=20
if [ $a == $b ]
then
echo "a 不等于 b"
fi
2、if else 语法格式:
if condition
then
command1
command2
...
commandN
else
command
fi
例如:
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
else
echo "a 不等于 b"
fi
3、if else-if else 语法格式:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
例如:
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
4、for 循环一般格式为:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
写成一行:
for var in item1 item2 ... itemN; do command1; command2… done;
例如:
for value in 1 2 3 4 5
do
echo "The value is: $value"
done
输出结果为:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
5、while 语句格式为:
while condition
do
command
done
例如:
int=1
while(( $int<=5 ))
do
echo "while 语句输出:$int"
let "int++"
done
输出结果为:
while 语句输出:1
while 语句输出:2
while 语句输出:3
while 语句输出:4
while 语句输出:5
6、case语句格式:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
case工作方式如上所示。取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
例如:
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
输出结果为:
输入 1 到 4 之间的数字:
你输入的数字为:
3
你选择了 3
7、跳出循环-break命令:
break命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。
例如:
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
输出结果为:
输入 1 到 5 之间的数字:3
你输入的数字为 3!
输入 1 到 5 之间的数字:7
你输入的数字不是 1 到 5 之间的! 游戏结束
8、跳出循环-continue命令:
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
对上面的例子进行修改:
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句 echo "游戏结束" 永远不会被执行。
9、esac
case的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。
Shell 函数
shell中函数的定义格式如下:
[ function ] funname [()]
{
action;
[return int;]
}
注意:
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)。
例如:
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
输出结果为:
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
下面定义一个带有return语句的函数:
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
输出结果为:
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3 !
函数返回值在调用该函数后通过 $? 来获得。
注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
函数参数
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过1表示第一个参数,$2表示第二个参数...
带参数的函数示例:
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
输出结果为:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
注意:{10}。当n>=10时,需要使用${n}来获取参数。
脚本下载地址:first.sh
参考链接:Shell 脚本教程