一、shell简介
shell其实指的是shell环境,是软件和OS(操作系统)之间的通信接口(软件的执行操作可以被shell翻译成OS识别的指令,从而进行调度硬件进行工作)。shell相对于os是独立的接口,linux上有多种shell接口,比如/bin/sh,/bin/bash,/usr/bin/sh,/usr/bin/bash,用户可以选择任意一个作为环境接口与OS进行通信调度。
eg:查看系统中有哪些shell可以使用
eg:查看当前Linux正在使用的shell环境
shell环境(shell命令解释器)有很多功能:比如
1、命令记忆功能
2、命令和文件名补全功能
3、命令别名设置功能
4、作业控制、前台、后台切换功能
5、通配符功能
6、编程语言功能
在公司或者生产环境中所说shell脚本指的就是shell的其中一个强大功能而已。即它支持多种编程语言里常见的特征,比如分支和循环结构,函数,变量和数组等这些编程语法。并且一旦掌握后它将成为你的得力工具。只要能在提示符界面上输入的命令都能放到一个可执行的shell程序里,这意味着用shell语言能简单地重复执行某一任务。
二、shell脚本的编程规范
2.1 shell脚本编写的规范
1. 文件名的扩展名是*.sh
2. 文件里的第一行是用来指定使用哪一种shell环境来解析本文件
eg:
#!/bin/bash <---必须#!开头 shell环境写绝对路径
3. 空行会被忽略
4. #用来注释, 必须在行首
5. 命令 选项 参数之间如果有多个空格,会被解析成一个空格
6. tab键形成的空白,也被解析成一个空格。
2.2 如何运行脚本文件
方式1: 使用bash或sh指令 调度脚本文件
[root@linux01 ~]# bash test1.sh
[root@linux01 ~]# sh test1.sh方式2:直接写脚本文件的绝对路径或者是相对路径,相对路径时必须添加./ 该文件必须有rx权限
[root@linux01 ~]# /root/test1.sh
[root@linux01 ~]# ./test1.sh方式3:当脚本用于rw权限后,可以借助PATH环境变量里的一个路径来使用 /root/bin
[root@linux01 ~]# mkdir ~/bin
[root@linux01 ~]# mv ./test1.sh ~/bin
[root@linux01 ~]# test1.sh <------会被当成命令直接使用
因为Linux会为每一个登录用户在PATH环境变量中维护一个~/bin目录,实际上该目录不存在,属于提前维护的。
2.3 shell脚本的变量
命名规范
- 由字母,数字,_组成,但是数字不能作为开头字符
- 字母习惯使用大写。
- 中间不能有空格。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)
- 严格区分大小写
使用规范
- 直接定义变量名称,没有类型需要强调(类似于数学中:x=1,y=2,z=x+y)
- 赋值时,"=" 前后不能有空格
- 命令的执行结果赋值给变量时,使用反单引号 如:TIME=`date`
- 调用变量时,必须使用$ 格式: $变量名 或 ${变量名}
小贴士: 反单引号也可以使用$() 比如 `date` 也可以写成 $(date)
2.4 变量的分类
shell脚本中的变量可以分局部变量、环境变量、位置变量、特殊意义的变量
局部变量
定义的变量只能在当前程序中使用,不能在其他程序中使用,如子程序
[root@linux01 ~]# NAME=lalala # 在当前shell程序中定义一个NAME变量
[root@linux01 ~]# echo $NAME
lalala[root@linux01 ~]# bash # 进入子程序(也就是另起一个shell程序)
[root@linux01 ~]# echo $NAME # 子程序中NAME是没有值的,也就是未定义[root@linux01 ~]# exit # 退出子程序
exit局部变量可以重新赋值 区分大小写
--- 只读变量
[root@linux01 ~]# NAME='zhaoyouting'
[root@linux01 ~]# echo $NAME
zhaoyouting
[root@linux01 ~]# readonly NAME #设置成只读变量
[root@linux01 ~]# echo $NAME
zhaoyouting
[root@linux01 ~]# NAME='JIAJINGWEN' #只读变量不能被再次赋值
bash: NAME: 只读变量
[root@linux01 ~]# address='changchun'
[root@linux01 ~]# echo $address
changchun--- 删除变量
[root@linux01 ~]# unset address #删除变量
[root@linux01 ~]# echo $address[root@linux01 ~]# unset NAME #只读变量不能被删除
环境变量
当前程序中定义的变量,其他程序中也可以使用,我们就称之为环境变量
[root@linux01 ~]# export name='nihao' # 定义局部变量,并导出成环境变量
[root@linux01 ~]# bash #进入子程序
[root@linux01 ~]# echo $name # 打印变量,发现有值。
nihao[root@linux01 ~]# address='beijing' #定义局部变量
[root@linux01 ~]# export address #将局部变量导出成环境变量
[root@linux01 ~]# bash #进入子程序
[root@linux01 ~]# echo $address # 打印变量,发现有值。
beijing在文件中定义环境变量
[root@linux01 ~]# vim test03.sh
#!/usr/bin/sh #先定义变量 MY_HOME=/root/bin #定义变量,直接导出 export MY_PATH=/root/bin/ssh #统一导出 export MY_HOME
[root@linux01 ~]# source test03.sh # 如果想要将文件中的环境变量在命令行界面生效,需要使用source指令
[root@linux01bin]# echo $MY_PATH
/root/bin/ssh
[root@linux01bin]# echo $MY_HOME
/root/bin
如何检查系统的环境变量
[root@linux01 ~]# export
或
[root@linux01 ~]# env
位置变量
linux系统为命令行提供了特殊的位置变量$num ,num是从0开始的连续自然数
[root@linux01 ~]# vim bin/test2.sh
#!/bin/bash echo $0 #一般指命令 echo $1 echo $2 echo $4
[root@linux01 ~]# chmod 700 bin/test2.sh #注意给权限
测试脚本[root@linux01 ~]# test2.sh zhuzhuxia 开心超人 喜羊羊 棒棒糖
/root/bin/test2.sh
zhuzhuxia
开心超人
喜羊羊注意: $0 指的是命令,$1开始的值称之为位置参数
$10会被解析成$1和0的无缝拼接,因此想要表达10位置的参数,需要将数字使用大括号括起来${10}
.........$11-->${11}
特殊意义的变量
$* : 将命令行上的所有位置参数当成一个字符串整体看待,即以"$1 $2 … $n"的形式输出所有参数
$@ : 将命令行上的所有位置参数区分看待,即每一个参数都是一个字符串
$# : 位置参数的个数
$? : 上一个命令执行的结果。0表示成功,其他值表示失败,值的范围为0~255
$$ : 当前进程的PID值
$! : 后台进程的最后一个进程的PID想要测试出结果,后台进程需要在脚本中书写,和$!在同一个脚本中测试一下:
[root@linux01 ~]# vim bin/test3.sh
#!/bin/bash echo '$0的值:'$0 echo "第一个位置参数:"$1 echo '$*的值:'$* echo '$@的值:'$@ echo '$#的值(参数个数):'$# echo '$?的值:'$? echo '$$的值(当前进程PID):'$$ echo '$!的值(后台进程最后一个进程的PID):'$!
[root@linux01 ~]# chmod 700 bin/test3.sh
[root@linux01 ~]# test3.sh 1 2 3 4 5 6 7 8 9
$0的值:/root/bin/test3.sh
第一个位置参数:1
$*的值:1 2 3 4 5 6 7 8 9
$@的值:1 2 3 4 5 6 7 8 9
$#的值(参数个数):9
$?的值:0
$$的值(当前进程PID):3306
$!的值(后台进程最后一个进程的PID):
2.5 三个常用的命令
read指令:
让变量接收键盘录入的数据
特点:有阻塞程序的效果,程序运行到read指令时,卡住了,表示等待键盘录入,回车后表示录入结束,程序继续执行。
格式: read [选项] variable
选项解析:
-p:用于指定提示信息
-n:规定录入字符串长度,达到此长度,自动结束
-t :对录入进行时间限制,单位是秒
-s:隐藏输入的数据
[root@linux01 ~]# read -p "请输入用户名:" -n 8 user #达到8个长度,自动结束
请输入用户名:abcdefgh
[root@linux01 ~]# echo $user
abcdefgh[root@linux01 ~]# read -p "请输入用户名:" -n 8 -t 5 user #超过5秒自动结束,但是变量没有值
请输入用户名:aaa
[root@linux01 ~]# echo $user没有值
[root@linux01 ~]# read -p "请输入密码:" -n 8 -s password
请输入密码: 输入密码不显示输入的内容
[root@linux01 ~]# echo $password
123123
expr指令:
这个命令可以对整数表达式进行运算。注意,运算符前后必须要有空格符
//可以直接运算
[root@linux01 ~]# expr 1 + 2
3//给变量赋值需要加单引号或者$( )
[root@linux01 ~]# result=`expr 1 + 2`
[root@linux01 ~]# echo $result
3[root@linux01 ~]# result=$(expr 1 + 2)
[root@linux01 ~]# echo $result
3//多层嵌套需要单引号
[root@linux01 ~]# expr 1 + `expr 2 + 3` # 嵌套一层expr
6//乘法运算需要转义
[root@linux01 ~]# expr 2 \* 3 # 乘法运算,*需要转义字符
6//反单引号里的单引号也需要转义
[root@linux01 ~]# n=3
[root@linux01 ~]# m=2
[root@linux01 ~]# result=`expr 1 + \`expr $n + $m\`` #反单引号里的反单引号需要转义
[root@linux01 ~]# echo $result
6
test指令:
文件类型检测:
test -e filename 检测filename是否存在
test -d filename 检测filename是不是目录
test -f filename 检测filename是不是普通文件
test -L filename 检测filename是不是软链接文件文件属性检测
test - r filename 检测filename是否有可读权限
test -w filename 检测filename是否有可写权限
test -x filename 检测filename是否有执行权限
两个文件的比较test file1 -nt file2 检测 file1 是否比file2 新
test file1-ot file2 检测 file1 是否比 file2 旧
test file1-ef file2 检测 file1和 file 2 是否为同一文件两个整数的比较
tesl n1 -eq n2 检测 n1 与 n2 是否相等
test n1 -ne n2 检测n1与 n2 是否不等
test n1 -gt n2 检测n1 是否大于 n2(greater than)
test n1 -lt n2 检测n1 是否小于 n2(less than)
test n1 -ge n2 检测n1 是否大于等于n2
test n1 -le n2 检测n1 是否小于等于n2字符串的数据
test -z string 检测string 是否为空
test -n string 检测string 是否不为空 -n 也可以省略
test string1 == string2 检测string1与string2是否相等
test string1 != string2 检测string1与string2 是否不相等多条件连接test -r filename a -x filename
-a and 两个检测都成立,返回true
-o or 只要有一个检测成立,就返回true
| 非
-
通常test命令不单独使用,而是与if语句连用,或者是放在循环结构中。
-
判断符号[ ]
除了好用的test外,我们还可以使用中括号来进行检测条件是否成立。
[ -r filename ] : 检测filename是否有可读权限
[ -f filename -a -r filename ] : 检测filename是不是普通文件并且有可读权限
2.6 shell的字符串类型
字符串的基本用法
- 字符串不能单独使用,必须要配合变量。
- 字符串可以使用单引号,也可以使用双引号,也可以不用引号单引号:
- 单引号内的任何字符没有任何意义,都会原样输出, echo 'hello $name world'
- 单引号内使用变量是无效的,单引号内不能出现单引号双引号:
- 双引号内可以使用变量 echo "hello $name world"
- 双引号内可以使用转义字符 echo -e "hello\\nworld"
- 在字符串拼接操作时,我们可以进行无缝拼接,或者是在双引号里使用变量
echo "第一个位置参数是"$1
echo "第一个位置参数是$1"
字符串的长度
三种方法:
${#variable}
expr length "${variable}"
expr length $variableeg:
[root@linux01 ~]# name=gaoyuanyuan
[root@linux01 ~]# echo ${#name}
11[root@linux01 ~]# expr length "${name}"
11
[root@linux01 ~]# len=`expr length ${name}`
[root@linux01 ~]# echo $len
11
子字符串的截取
字符串的下标从0开始。而截取有如下写法:(正着从0开始数,倒着从1开始数)
${variable:startIndex} : 从startIndex下标开始,截取到最后
${variable:startIndex:length} : 从startIndex下标开始,截取length个长度
${variable:0-num} : 倒数第num个开始,截取到最后
${variable:0-num:length} : 倒数第num个开始,截取length个长度
[root@linux01 ~]# vim bin/test4.sh
#!/bin/bash url="http://www.baidu.com" substr=${url:4} echo $substr substr=${url:4:4} echo $substr substr=${url:0-4} echo $substr substr=${url:0-6:4} echo $substr
[root@linux01 ~]# bash bin/test4.sh
://www.baidu.com
://w
.com
du.c
2.7 Shell的数组类型
Array的定义与使用规则
定义格式: variable=(值1 值2 … 值n)
注意:元素之间除了使用空格作为分隔符,还可以使用换行符。或者:
name[0]=值1
name[1]=值2
…
name[n]=值n使用规则:
- 在/bin/bash这个shell中,只有一维数组的概念,并且不限定数组的长度。
- 数组的元素下标是从0开始的
- 获取数组的元素要使用下标
- 下标使用不当,会报错。
-- 正数的下标不会报错,
-- 负数的下标表示元素的倒数方式 -1表示倒数第一个 -2表示倒数第二个, 倒数的数字一旦超出元素的个数,就会报错举些栗子:
[root@linux01 ~]# names=(1 2 3) #定义三个长度的数组
[root@linux01 ~]# echo ${names[0]}
1
[root@linux01 ~]# echo ${names[1]}
2
[root@linux01 ~]# echo ${names[2]}
3
[root@linux01 ~]# echo ${names[3]} #打印第四个元素,数组中没有第四个,不会报错[root@linux01 ~]# echo ${names[-1]} #打印数组中的倒数第一个元素
3
[root@linux01 ~]# echo ${names[-2]}
2
[root@linux01 ~]# echo ${names[-3]}
1
[root@linux01 ~]# echo ${names[-4]} # 打印数组中的倒数第四个元素,不存在,则报错
bash: names: 坏的数组下标
数组的读取
${variable[index]}: 读取index索引上的元素
${variable[*]} 或者 ${variable[@]}:读取所有元素
${#variable[*]} 或者 ${#variable[@]} : 读取数组的长度举个栗子:
[michael@master ~]$ vim bin/test5.sh
#!/bin/bash name=(lele lyly makabaka) address=(changchun #分隔符为换行 beijing shanghai shenzhen) hobby[0]='hi' hobby[1]='happy' hobby[3]='hello' echo ${name[0]} echo ${address[*]} echo ${address[@]} echo ${#address[*]} echo ${#hobby[@]}
[michael@master ~]$ bash bin/test5.sh
lele
changchun beijing shanghai shenzhen
changchun beijing shanghai shenzhen
4
3
2.8 Shell的分支结构
if分支
一条分支的写法:
if [ 条件 ] ;then #注意 条件的内容要空格隔开 不能直接写><=等符号(如果一定要用符号,要用双层小括号代替中括号)
执行逻辑
fi
带else的写法
if [ 条件 ] ;then # [] 换成 (()) 可以使用 大于号,小于号等
执行逻辑
else
执行逻辑
fi
多分支的写法
if [ 条件 ] ;then
执行逻辑
elif [ 条件 ];then
执行逻辑
else
执行逻辑
fi
注意:条件后面应该有一个分号 将条件和then关键字隔开。如果不想加分号,then需要换行书写。
举个大栗子:
[root@linux01 ~]# vim bin/test6.sh
#!/bin/bash m=10 n=20 if [ $m -lt $n ] then echo "m>n" fi read -p '请给x赋一个整数:' x read -p '请给y赋一个整数:' y if [ $x -gt $y ];then echo "x>y" else echo "x<y" fi echo '---------------------------------' # 如果想要在条件中使用>,<这类的符号,可以将条件外的中括号换成双层小括号, $也可以省略不写 read -p '请给a赋一个整数:' a read -p '请给b赋一个整数:' b if (( a >= b ));then echo "a>=b" else echo "a<b" fi echo '-----------------多分支的测试----------------' read -p '请给c赋一个整数:' c read -p '请给d赋一个整数:' d if [ $c -gt $d ];then echo "c>d" elif [ $c -eq $d ];then echo "c=d" else echo "c<d" fi
结果:
[root@linux01 bin]# bash test6.sh
m>n
请给x赋一个整数:10
请给y赋一个整数:20
x<y
---------------------------------
请给a赋一个整数:4
请给b赋一个整数:5
a<b
-----------------多分支的测试----------------
请给c赋一个整数:2
请给d赋一个整数:2
c=d
case分支
匹配,选择匹配成功的那块进行作业
case ... in
value1)
执行逻辑
;;
value2)
执行逻辑
;;
value3)
执行逻辑
;;
.......
valueN)
执行逻辑
;;
esac//最后一个分支匹配,用通配符*,表示不满足之前的所有分支,相当于default分支。
举个栗子:
[michael@master ~]$ vim bin/test7.sh
#!/bin/bash case $1 in start) systemctl start firewalld systemctl start NetworkManager ;; stop) systemctl stop firewalld systemctl stop NetworkManager ;; status) systemctl status firewalld systemctl status NetworkManager ;; esac
[root@linux01 bin]# bash test7.sh start
启动firewalld和NetworkManager服务项
[root@linux01 bin]# bash test7.sh stop
关闭firewalld和NetworkManager服务项
[root@linux01 bin]# bash test7.sh status
查看firewalld和NetworkManager服务项状态
[root@linux01 bin]# bash test7.sh enable
输入了其他不存在项目
来道题:
在一个脚本里,使用read命令 读取year和month。然后输出year年month月有多少天(分别用if和case实现)
if方法:
#!/bin/bash read -p 'input the year:' year read -p 'input the month:' month if [ $month == '2' ];then if [ `expr $year % 4` -eq 0 ] && [ `expr $year % 100 ` -ne 0 ] || [ `expr $year % 400 ` -eq 0 ];then echo '29days' else echo '28days' fi elif [ $month == '4' ] || [ $month == '6' ]|| [ $month == '9' ] || [ $month == '11' ];then echo '30days' else echo '31days' fi
case方法:
#!/bin/bash read -p "请输入年份:" YEAR read -p "请输入月份:" MONTH case $MONTH in 1|3|5|7|8|10|12) echo "$YEAR年$MONTH月有31天" ;; 4|6|9|11) echo "$YEAR年$MONTH月有30天" ;; 2) if [ $[ YEAR%4] == 0 -a $[YEAR%100] != 0 -o $[ YEAR%400] == 0 ];then echo "$YEAR年$MONTH月有29天" else echo "$YEAR年$MONTH月有28天" fi ;; esac
2.9 Shell的循环结构
while循环结构
while [ 条件表达式 ]
do
#作业内容
done
举些栗子:
1.打印10次 hello shell
#!/bin/bash count=0 while [ $count -lt 10 ] do echo "hello shell" #count=`expr $count + 1` #count=$(expr $count + 1) #count=$[ $count + 1 ] #count=$[count+1] let count++ done
2.计算1~100以内所有的奇数之和
#!/bin/bash num=1 sum=0 while [ $num -lt 100 ] do if [ $[$num % 2] -ne 0 ];then sum=$[sum+num] fi let num++ done echo "奇数和为:"$sum
3.使用循环和read命令,给一个数组names,赋值10个元素,如果有个元素是exit。就直接退出循环
#!/bin/bash count=0 while [ $count -lt 10 ] do read -p "请输入第$[count+1]个元素:" names[count] if [ ${names[count]} == exit ];then break fi let count++ done echo "names数组的元素为:"${names[*]}
或者:
#!/bin/bash count=0 while [ $count -lt 10 ] do read -p '输入数组元素:' num if [ $num == 'exit' ];then echo'退出' break; fi names[$count]=$num let count++ done echo ${names[*]}
until循环结构
当条件成立时,就终止循环,条件不成立时,就一直循环下去。
until [ 条件表达式 ]
do
#作业内容
done
设计输入密码错误超过5次自动退出的程序
#!/bin/bash read -p "请输入密码:" password count=0 until [ $password == "123456" ] do if [ $count -eq 4 ]; then echo "密码错误超过5次,自动退出" break fi let count++ read -p "请重新输入密码:" password done
for循环
第一种:
for 变量 in 列表
do
执行逻辑
done
列表的表示方式:
方式1: 使用空格隔开的一堆数据,比如
monday tuesday wenseday thursday friday saturday sundayeg:
#!/bin/bash
sum=0
for num in 1 2 3 4 5 6 7 8
do
sum=$[ sum + num]
done
echo "sum的值为$sum"结果为:sum的值为36
方式2: 命令的返回结果为多行或多列的情况 ls ~eg:
for filename in $(ls /)
do
echo "文件名:"$filename
done结果为:~下所有的文件名字
方式3: 使用命令seq返回列表,语法:seq n1 n2 表示产生一个从n1到n2的自然数列表
也可以使用{n1..n2}的这种写法eg:
for num in $(seq 1 10)
do
echo "num的值为:$num"
done或者:
for num in {1..10}
do
echo "num的值为$num"
done结果为:
num的值为:1
num的值为:2
num的值为:3
num的值为:4
num的值为:5
num的值为:6
num的值为:7
num的值为:8
num的值为:9
num的值为:10
方式4: cut指令的用法: cut -d '分隔符' -fn filename /etc/passwd
用来切分文件中的每一行的数据,使用分隔符切分,-fn中的n是获取第n列的意思eg:
for column in $(cut -d ":" -f1 /etc/passwd)
do
echo $column >> /root/bin/result.txt
done从 /etc/passwd 文件中提取用户名,并将提取到的用户名写入到 /root/bin/result.txt文件中。
第二种:适合在数值的处理上使用
for ((变量初始化;循环条件;变量的改变))
do
执行逻辑
done
1. 计算1~100的所有偶数的和
#!/bin/bash sum=0 for((i=0;i<=100;i++)) do if [ $[i%2] == 0 ];then sum=$[sum+i] fi done echo "1~100的偶数之和:"$sum
2.打印出1000以内所有素数
#!/bin/bash i=0 count=0 while [ $i -le 1000 ] do for((j=2;j<i;j++)) do if [ $[i%j] == 0 ];then break fi done if [ $i == $j ];then let count++ # 每10个数 一行 if [ $[ count%10 ] == 0 ];then echo "$i " else # 取消换行 echo -e " $i\c" fi fi let i++ done echo ""
2.10 select表单循环
有的时候,需要将一些数据设置成表单的模式,供用户来选择。我们就可以使用select表单循环结构。(注意只能选择表单里的选项,选择表单没有的可能会报错)
select variable in 列表
do
#作业内容
done
eg:选择周几
[root@linux01 ~]# vim ~/bin/test12.sh
#!/bin/bash select var in monday tuesday wenseday thursday friday saturday sunday do echo "your option is $var" if [ $var == "sunday" ];then break fi done
结果:
[root@linux01 ~]# sh ~/bin/test12.sh
1) monday 3) wenseday 5) friday 7) sunday
2) tuesday 4) thursday 6) saturday
#? 2
your option is tuesday
#? 1
your option is monday
#? 2
your option is tuesday
#? 7
your option is sunday #然后退出
2.11 shift指令的应用
对于linux系统来说,在shell中,shift命令可以使参数产生位移。
[root@linux01 bin]# vim ~/bin/test13.sh
#!/bin/bash echo "all parameters ========>: $@" echo "the first parameters ==>: $1" echo "---------------------黄金分割线---------------------------" shift echo "all parameters ========>: $@" echo "the first parameters ==>: $1" echo "---------------------黄金分割线---------------------------" shift echo "all parameters ========>: $@" echo "the first parameters ==>: $1" echo "---------------------黄金分割线---------------------------" shift echo "all parameters ========>: $@" echo "the first parameters ==>: $1"
结果:
[root@linux01 bin]# bash test13.sh a b c d e f
all parameters ========>: a b c d e f
the first parameters ==>: a
---------------------黄金分割线---------------------------
all parameters ========>: b c d e f
the first parameters ==>: b
---------------------黄金分割线---------------------------
all parameters ========>: c d e f
the first parameters ==>: c
---------------------黄金分割线---------------------------
all parameters ========>: d e f
the first parameters ==>: d
计算所有的位置参数之和
[root@linux01 bin]# vim ~/bin/test14.sh
#!/bin/bash sum=0 until [ "$1" == "" ] do sum=`expr $sum + $1 ` shift #使参数向左移动 done echo "sum:$sum"
结果:
[root@linux01 bin]# bash test14.sh 1 2 3 4 5 6 7 8
sum:36
2.12 Shell的函数
语法:
function funcName(){
}
语法解析:
1、关键字function 可加可不加
2、调用时,直接写函数名称,不添加()。
3、因为script是从上往下,从左往右执行的,所以,要先定义,后调用 ---->看eg1
4、return关键字,可加可不加,看需求
加的话,返回值只能是0~255的整数,使用$?获取返回值 封闭式运算---->看eg2
5、可以使用$n位置参数变量向函数里传值 ---->看eg2
eg1:
[root@linux01 bin]$ vim test15.sh
#!/bin/bash function sum(){ a=0 for i in {1..100} do a=$[a+i] done echo "1~100 的和:$a" } sum # 调用函数sum
方法一:直接执行
[root@linux01 bin]$ bash test15.sh
1~100 的和:5050方法二:source指令引入到当前shell环境:
[root@linux01 bin]$ source test15.sh #另外一种执行方式
1~100 的和:5050
[root@linux01 ~]$ sum
1~100 的和:5050eg2:
[root@linux01 bin]$ vim test16.sh
#!/bin/bash #定义函数func2 func2(){ result=$[ $1 + $2 ] echo "result的值为$result" # 使用return 书写返回值 return $result } #调用函数,并指定位置参数,调用函数其实就相当于在命令行上操作,函数名后的就是位置参数 func2 100 156 echo "func2的返回值为$?"
[root@linux01 bin]# bash test16.sh
result的值为256
func2的返回值为0 <===因为 100+156 为256 超出255,开始从0循环,衔尾蛇[root@linux01 bin]# source test16.sh #引入当前shell环境中
result的值为256
func2的返回值为0
[root@linux01 bin]# func2 100 157 #直接测试func2
result的值为257
[root@linux01 bin]# echo $? #获取func2的返回值
1
[root@linux01 bin]# func2 100 158 #再测试func2
result的值为258
[root@linux01 bin]# echo $? #再获取func2的返回值
2
2.13 脚本之间的引入
即在一个脚本中,使用另外一个脚本,调用方式如下:
. filename
或
source filename
[root@ linux01 ~]# vim ~/bin/test17.sh
#!/bin/bash function f1(){ echo "hello,welcome to china" }
[root@ linux01 ~]# vim ~/bin/test18.sh
#!/bin/bash source /root/bin/test17.sh # 或者 # . /root/bin/test17.sh echo "micheal" f1
结果:
[root@ linux01 ~]# vim ~/bin/test18.sh
micheal
hello,welcome to china
2.14 脚本的调试方式
set -x:如果想要查看脚本中的每一行代码在运行时的样子,可以在前面添加set -x
bash -x file.sh 参数:如果set -x添加在整个脚本的前面,那就是查看整个脚本的运行样子,如下方式亦可,在命令行上。
bash -n file.sh:-n的作用:不执行脚本里的逻辑,只检查脚本中的语法是否有错误。如果有,就打印错误
bash -v file.sh:-v的作用打印脚本里的所有信息到屏幕上,相当于cat指令查看
set -x 可以书写到脚本中:调试set -x 以下的脚本内容,之前的内容正常
[root@linux01 bin]# vim test19.sh
#!/bin/bash a=$1 set -x b=3 echo "b:"+$b c=$a echo $a
[root@linux01 bin]# bash -x test19.sh 10
+ a=10
+ b=3
+ echo b:3
b:3
+ c=10
+ echo 10
10-x的作用:可以将每一行中的$变量 替换成具体的值,进行显示