引入
完成以下任务
:
判断用户家目录下(~
)下面有没有一个叫
test
的文件夹
如果没有,提示按 y
创建并进入此文件夹,按
n
退出
如果有,直接进入,提示请输入一个字符串,并按此字符串创建一个文件,如果此
文件已存在,提示重新输入,重复三次自动退出,不存在创建完毕,退出
简单的进行命令堆积无法完成以上任务,这就需要学习相应的 shell
脚本语法规则了
简介
Shell的概念
是一种应用程序,
也是一种设计语言
作为应用程序
系统分为,
硬件层
,Liunx
系统层
,Shell,
应用程序层
,
如图
1
此时Shell
的作用是沟通应用程序层与
Liunx
系统层
,
即
Shell
解析器
Shell解析器常用的有三种
,
分别是
sh,ash,bash,
一般情况下使用
bash
可以使用echo $SHELL
查看使用的那种解析器
,
如图
2
作为设计语言
概念:shell
脚本语言
,
不需要编译
,
直接解析执行
(
批处理
)
优点:
简化我们对系统的管理与应用程序的部署过程
名词
:
批处理:
大量的循环的数据处理,如扫描当前根目录下是否存在
a.txt,
此时需要在当前根目录所有文件夹中一一寻找
脚本语言:
我们只需使用任意文本编辑器,按照语法编写相应程序,
增加可执行权 限,即可在安装
shell
命令解释器的环境下执行的代码语言
,
如
python,html,css
等
Shell脚本的分类
系统调用
这类脚本无需用户调用,系统会在合适的时候调用,如:/etc/profile
、 ~/.bashrc 等
/etc/profile:
此文件为系统的每个用户设置环境信息,
当用户第一次登录时
,
该文件被执行
, 系统的公共环境变量在这里设置
开机自启动的程序,一般也在这里设置
注意:
如果在该文件中配置
,
需要从新登录用户才可生效
~/.bashrc
用户自己的家目录中的.bashrc
登录时会自动调用,打开任意终端时也会自动调用
这个文件一般设置与个人用户有关的环境变量,如交叉编译器的路径等等
/etc/profile
与
~/.bashrc
的关系
,
如下图
用户编写
需要手动调用
注意
:
无论是系统调用的还是需要我们自己调用的,其语法规则都一样
第一个Shell脚本
步骤 :
1,创建文件
,shell
脚本一般以
.sh
结尾
,
也可以不是或者没有
2,编写代码
3,执行脚本
如:
1,创建
Hello.sh
文件
2,编写以下代码
#!/bin/bash
echo "Hello Shall"
3,执行
hello.sh
文件
./Hello.sh
说明
:
#!用来声明脚本由什么
shell
解释,否则使用默认
shell
#表示注释本行
注意 :
创建文件时
:
如果是在windows
中创建编写的
Shell
脚本文件
,
拖拽到
Liunx
下无法运行
,
因为 Windows与
Liunx
下
\
表示的含义不同
,
所以导致程序无法被识别
解决方案
1:
在Liunx
中使用
vim
编辑器
,
在最后一行模式输入
set ff=unix
解决方案
2:
在Linux
中安装
dos2unix,
使用
dos2unix
转换
步骤:
1,命令行输入:sudo apt-age install dos2unix
2,命令行输入:dos2unix
文件地址
编写代码:
# 注释
#! 用来声明脚本由什么
shell
解释,否则使用默认
shell
echo 输出
执行脚本方式:
方式1:
使用
sh
或
bash
sh 文件路径
bash 文件路径
方式2:./
文件路径
需要可执行权限,
添加权限命令
:chmod +x
文件路径
+增加权限
-减少权限
x:可执行
以上方式会开启子Shell
如
:
chmod +x hishell.sh
方式3:source
文件名或
.
文件名
source 文件路径 借鉴
cshell
. 文件路径 借鉴
bash
以上方式不会开启子Shell
开启子Shell
与不开启的区别
开启子Shell
后
,
子
Shell
中的变量父
Shell
不可见
区别
:
./和
bash
执行过程基本一致,
bash明确指定
bash
解释器去执行脚本,脚本中
#!
指定的解释器不起作用
./前者首先检测
#!
,使用
#!
指定的
shell
,如果没有使用默认的
shell
用./
和
bash
去执行会在后台启动一个新的
shell
去执行脚本
用.
去执行脚本不会启动新的
shell,
直接由当前的
shell
去解释执行脚本
变量
分类
按是否为系统提供分类
系统变量
自定义变量
按作用范围分类
全局变量:
当前
Shell
中的所有
Shell
都可使用
(
自己与其中的子
Shell)
局部变量:
当前
Shell
中使用
(
自己使用
)
系统预定义变量
常用系统变量
如
:HOME,PWD,SHELL,USER
查看系统变量的值
语法
:
echo 变量名
如
:
echo $HOME
显示系统中的全局变量
语法
:
env或
printenv
如
:
env
printenv
显示当前
Shell
中的所有变量
语法
:
set
如
:
set
自定义变量
基本语法
定义变量:
变量名=
变量值
;
注意
:
=号前后不能有空格
声明的变量为局部变量
撤销变量
unset 变量名
声明只读变量
语法
:
readonly 变量
注意
:
只读变量不能撤销,
不能修改值
示例
:
#!/bin/bash
readonly num=10
#unset num
num=100
echo $num
引用变量
$变量名
注意
:
如果变量不存在返回空
导出变量
作用
:
将当前变量导入到系统变量中
语法
:
export 变量名
注意
:
只在当前终端有效
需要使用source
或
.
执行
示例
:
代码
export DATA=1000
运行
source 文件路径
查看变量
env
declare -i:
将变量强制转换为数字
#!/bin/bash
#注意:必须使用./运行
declare -i DATA=1
DATA=$DATA+1
echo $DATA
定义规则
1,变量名由字母
,
数字
,
下划线组成
,
不能使用数字开头
,
环境变量名不建议大写
2,=号两侧不能有空格
3,在
bash
中
,
变量默认类型为都是字符
,
无法直接进行数值运算
4,变量值如果有空格
,
需要使用双引号或单引号包裹
注意
:""
与
''
的区别
""会解析变量值
''不会解析变量值
示例
:
#!/bin/bash
num
=
1000
echo
"num=
$num
"
echo
'num=$num'
预设变量
$#:传给
shell
脚本参数的数量
$*:传给
shell
脚本参数的内容
$1、
$2
、
$3
、
...
、
$9
:运行脚本时传递给其的参数,用空格隔开
$?:命令执行后返回的状态
"$?"用于检查上一个命令执行是否正确
(
在
Linux
中,命令退出状态为
0
表示该命令 正确执行,任何非 0
值表示命令出错)
。
$0:当前执行的进程名
$$:当前进程的进程号
"$$"变量最常见的用途是用作临时文件的名字以保证临时文件不会重复
示例
#!/bin/bash
# 执行命令sh ./07_code.sh a b c
echo "参数个数:$#"
echo "参数内容:$*"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "第三个参数:$3"
#ps是用来查看系统进程的命令 -A
#常用参数
#-A 显示所有进程(同-e)
#-a 显示当前终端的所有进程
#-u 显示进程的用户信息
#-o 以用户自定义形式显示进程信息
#-f 显示程序间的关系
ps -A | grep bash
echo "指令结果:$?"
echo "进程名称:$0"
echo "进程号:$$"
脚本变量的特殊用法
"":包含的变量会被解释
'':包含的变量会作为字符串处理
``:反引号中的内容作为系统命令,并执行其内容,可以替换输出为一个变量
\:同
c
语言
\n \t \r \a
等
echo
命令需加
-e
转义
(bash
解析器需求
)
( 命令
):
由子
shell
来完成
,
不影响当前
shell
中的变量
,
命令前后必须有空格
{ 命令
}:
在当前
shell
中执行
,
会影响当前变量
,
命令前后必须有空格
示例
#!/bin/bash
num=100;
echo "num=$num"
echo 'num=$num'
echo "当前时间:`date`"
echo '当前时间:`date`'
echo -e "abc\n123"
echo -e "##\n##"
(
num=1000
echo "()内打印num变量:$num"
)
echo "()外打印num变量:$num"
{
num=1
echo "{}内打印num变量:$num"
}
echo "{}外打印num变量:$num"
键盘录入
语法
read 变量名
或
read -p 提示内容 变量名
如
#!/bin/bash
num=0
# echo "请输入一个数:"
# read num
# 或
read -p "请输入一个数:" num
echo "num=$num"
条件测试语句
语法
语法1:test
条件
语法2:[
条件
]
注意
:
条件前后必须有空格
文件测试
文件测试:测试文件状态的条件表达式
-e 是否存在
-d 是否为目录
-f 是否为文件
-r 是否可读
-w 是否可写
-x 是否可执行
-L 是否连接
-c 是否字符设备
-b 是否块设备
-s 文件非空
示例 :
#!/bin/bash
read -p "请输入文件名:" fileName
#-e:测试文件是否存在
test -e $fileName
echo "是否存在:$?"
#-f是否为文件
test -f $fileName
echo "是文件吗:$?"
#-d是否为文件夹
test -d $fileName
echo "是文件夹吗:$?"
#-r是否可读
[ -r $fileName ]
echo "是否可读:$?"
#-w是否可读
[ -w $fileName ]
echo "是否可写:$?"
#-x是否可执行
[ -x $fileName ]
echo "是否可执行:$?"
字符串测试
= 两个字符串相等
!= 两个字符串不相等
-z 空串
-n 非空串
注意
:= !=
前后要有空格
示例
#!/bin/bash
str01="hello"
str02="world"
str03="hello"
[ $str01 = $str02 ]
echo "str01等于str02:$?"
[ $str01 = $str03 ]
echo "str01等于str03:$?"
test $str01 != $str02
echo "str01不等于str02:$?"
test $str01 != $str03
echo "str01不等于str03:$?"
[ -z $str01 ]
echo "str01是否是空串:$?"
[ -n $str01 ]
echo "str01是否不是空串:$?"
数值测试
-eq 数值相等
-ne 数值不相等
-gt 数
1
大于数
2
-ge 数
1
大于等于数
2
-le 数
1
小于等于数
2
-lt 数
1
小于数
2
示例
#!/bin/bash
num01=10
num02=3
# -eq 数值相等
test $num01 -eq $num02
echo "num01等于num02:$?"
# -ne 数值不相等
test $num01 -ne $num02
echo "num01不等于num02:$?"
# -gt 数 1 大于数 2
test $num01 -gt $num02
echo "num01大于num02:$?"
# -ge 数 1 大于等于数 2
[ $num01 -ge $num02 ]
echo "num01大于等于num02:$?"
# -le 数 1 小于等于数 2
[ $num01 -le $num02 ]
echo "num01小于等于num02:$?"
# -lt 数 1 小于数 2
[ $num01 -lt $num02 ]
echo "num01小于num02:$?"
扩展
#${num:-val} 如果num存在,返回num,否则返回val
echo ${x:-10}
#${num:=val} 如果num存在,返回num,否则返回val,并将val赋值给num
echo ${y:=10}
echo $y
复合测试
&&
:
command1 && command2
&&左边命令(
command1
)执行成功
(
即返回
0
)
shell
才执行
&&
右边的命令 (command2
)
||
command1 || command2
||左边的命令(
command1
)未执行成功
(
即返回非
0
)
shell
才执行
||
右边的命(command2
)
示例
#!/bin/bash
#输入一个数判断是否在0~100之间
read -p "请输入一个数" num
test $num -gt 0 && test $num -lt 100
echo "$num 是否在0~100之间:$?"
多重条件
-a:与
-o:或
!:非
示例
#!/bin/bash
#输入文件名称,判断文件是否可读可写可执行
read -p "请输入文件名称" fileName
test -r $fileName -a -w $fileName -a -x $fileName
echo "文件可读可写可执行:$?"
test -r $fileName -o -w $fileName
echo "文件可读或可写:$?"
test ! -x $fileName
echo "文件是否不可执行:$?"
控制语句
if语句
语法
1
if [ 条件
1 ];then
执行第一段程序
else
执行第二段程序
fi
示例
1
num01=10
num02=16
#获取两数最大值
if [ $num01 -gt $num02 ];then
echo $num01
else
echo $num02
fi
语法
2
if [ 条件1 ];then
执行第1段程序
elif [ 条件2 ];then
执行第2段程序
elif [ 条件3 ];then
执行第3段程序
...
else
执行第n段程序
fi
示例
#!/bin/bash
read -p "请输入考试成绩" score
if [ $score -lt 0 -o $score -gt 100 ];then
echo "成绩不应小于0,或大于100"
elif [ $score -lt 60 ];then
echo "D"
elif [ $score -lt 70 ];then
echo "C"
elif [ $score -lt 85 ];then
echo "B"
else
echo "A"
fi
示例
#!/bin/bash
#键盘输入一个文件名,判断是否存在改文件,
#如果存在显示文件内容
#如果不存在 创建该文件,并输入内容且输出文件内容。
read -p "请输入文件名称" fileName
#-e:是否存在
if [ -e $fileName ];then
#-d:是否为文件夹
#-o:或
#-s:是否为空文件
if [ -d $fileName -o -s $fileName ];then
echo "是文件夹或空文件"
else
cat $fileName
fi
else
#touch 创建文件
touch $fileName
read -p "请输入内容" info
#echo 输出的内容 >> 输出的地方,默认为控制台
echo $info >> $fileName
#cat 读取文件内容
cat $fileName
fi
case语句
语法
case $变量名
in
"值
1")
语句1
;;
"值
2")
语句2
;;
*)
语句3
;;
esac
扩展
:
exit 1 #退出
shell
示例
1
#!/bin/bash
read -p "是否继续" tag
case $tag in
"yes" | "YES")
#y* 以小写y开头
echo "继续"
;;
"no" | "NO")
echo "退出"
;;
*)
echo "输入有误"
;;
esac
示例
2
#!/bin/bash
read -p "是否继续" tag
case $tag in
y* | Y*)
#y* 以小写y开头
echo "继续"
;;
n* | N*)
echo "退出"
;;
*)
echo "输入有误"
;;
esac
for语句
语法
1
for (( 初始值
;
限制值
;
执行步阶
))
do
程序段
done
示例
#!/bin/bash
#计算100以内数之和
#declare -i s强制将s作为int型数值,需要使用./运行
declare -i s=0
declare -i sum=0
for (( s=0; s<=100; s++ ))
do
sum=$sum+$s;
done
echo $sum
语法
2
for var in con1 con2 con3 ...
do
程序段
done
示例
#!/bin/bash
str01="A"
str02="B"
str03="C"
for v in $str01 $str02 $str03
do
echo $v
done
示例
2
#!/bin/bash
#遍历文件夹
for fileName in `ls`
do
if [ -d $fileName ];then
echo "$fileName 是文件夹"
elif [ -f $fileName ];then
echo "$fileName 是文件"
fi
done
while语句
语法
while [ 条件
]
do
程序段
done
示例
#!/bin/bash
declare -i i=0
declare -i sum=0
while [ $i -le 100 ]
do
sum=$sum+$i
i=$i+1
done
echo $sum
扩展
变量名=$((
值
1 +
值
2 ))
变量名=$((
值
1 -
值
2 ))
变量名=$((
值
1 *
值
2 ))
变量名=$((
值
1 /
值
2 ))
变量名=$((
值
1 %
值
2 ))
变量名=$((
变量名
-- ))
变量名=$(( --
变量名
))
变量名=$((
变量名
++ ))
变量名=$(( ++
变量名
))
变量名=$(( -10 > 1 ? 10 : 1 ))
until语句
语法:
until [ condition ]
do
程序段
done
这种方式与 while
恰恰相反,当
condition
成立的时候退出循环,否则继续循环。
示例
#!/bin/bash
declare -i i=100
declare -i sum=0
#lt小于
until [ $i -lt 0 ]
do
sum=$sum+$i;
i=$i-1
done
echo $sum
函数
步骤
1,定义
2,调用
定义
语法
1
函数名(){
程序段
}
语法2
function 函数名
(){
程序段
}
调用
语法
函数名 参数1
参数
2
示例
#!/bin/bash
#函数定义
add(){
declare -i num=0
num=$1+$2
return $num
}
#函数调用
add 10 2
#获取结果输出
echo "返回值为:$?"
注意
当函数定义与函数调用不在一个文件中需要在函数调用所在的文件中使用source
引用函数定义的文件
示例
#myfun.sh定义函数
#!/bin/bash
function add(){
declare -i num=0
num=$1+$2
return $num
}
#24_code.sh调用函数
#!/bin/bash
#导入函数所在的文件
source myfun.sh
add 1 2
echo $?