1.Shell的环境和功能
1.1 Shell的概述
- Shell是操作系统与用户进行交互操作的界面
1.2 命令补全
- 命令补全的概念:命令补全是对于所输入命令的只能联想推测;命令补全功能可大幅提高命令的输入效率,并同时减少拼写错误的发生。
- 命令补全的使用:用TAB键单击来补全命令;用TAB键双击来列示智能匹配推测可能的命令
- 命令补全的限制:命令补全通常补全系统的命令路径下的命令;命令补全能够部分的补全命令行的命令参数(这里指操作参数)。
1.3 命令历史
- 命令历史的概念:命令历史是对于在命令行提示符下提交过的命令的历史记录;命令历史是命令行操作的痕迹;命令历史有条目保存的数量限制。
- 命令历史的查看:history
- 命令历史的清空:history -c
- 命令历史的引用:使用键盘的上下键逐条调阅最近的命令历史;使用 “!” 符号调用前端字符匹配的最近使用的命令(回车后会执行补全后的命令,谨慎操作)。
1.4 命令别名
- 命令别名的概念:命令别名是原命令的昵称;命令别名是shell的一种功能,而非命令的符号链接;命令别名在命令行提交时将被自动的字符替换。
- 命令别名的查看:alias
- 命令别名的设置:alias myls=‘ls -a’
1.5 通配符
- 通配符的概念:通配符是代表字符通用匹配的一种系统程序支持的特殊符号
- “ * ”通配符的使用:代表任意多个字符,eg:ls -l test.*
- “ ? ”通配符的使用:代表任意一个字符,eg:ls -l test?.?
- “ [ ] ”通配符的使用:代表范围中的一个字符,eg:ls -l test[0-9,a-z].txt
1.6 命令后台发送与作业控制
- 命令后台发送的概念:命令后台运行是指命令脱离命令行交互程序的控制而独立运行(不占用前台交互界面);
- 命令后台发送的使用:在原有命令的末端使用 “&” 符号即可将该命令发送至后台运行
- 命令作业控制的概念:命令作业控制是指系统对于命令作业的某种任务安排;
- 命令作业控制的操作:使用jobs命令就可以查看当前的后台作业任务;使用bg命令可以将当前命令作业(指当前被挂起的命令作业,挂起命令:kill -19 进程号)切换到后台;使用fg命令可以将最近的一个后台作业切换回前台。
2.Shell变量
2.1 Shell变量的概念
- shell变量的概念:shell变量是shell程序在内存中存储数据信息的容器
- shell变量的使用:shell变量的设置(也就是写入),eg:COLOR=red;shell变量的引用(也就屙是读取),eg:echo $COLOR eg: echo ${COLOR} (和别的字符连着写的时候,需要加大括号,比如echo ${COLOR}ball)
2.2 自定义变量
- 自定义变量的概念:自定义变量是用户自己命名的变量;自定义变量不得与系统命令的变量同名;
- 自定义变量的使用:自定义变量的设置(建议驼峰命令规则),eg:Day=Friday;自定义变量的引用,eg:echo “Today is ${Day}.”
2.3 环境变量
- 环境变量的概念:环境变量是指系统中用来存储环境信息数据的变量,通常系统配置初始提供提供(用env命令查看);
- 环境变量的使用:环境变量的使用方法和自定义变量一致,只是变量命名被约束(通常为大写,由系统定义)。
- 环境变量的导出和保存:用export命令可以将当前shell环境中的环境变量导出到子shell(当前shell派生出来的)中;环境变量可以保存到配置文件~/.bashrc中,供固化的长期使用。
- 常用的环境变量:PATH(系统路径),PS*系列变量
- PATH变量的概念:环境变量PATH存储系统命令的所在路径,通常为绝对路径;环境变量PATH提供了对于系统命令搜寻的便利,意义重大。
- PATH变量的使用:设置:eg:PATH=/home/name/bin:$PATH ;引用:eg:echo $PATH。
- 其他环境变量的使用:环境变量PS1存储命令行的提示符;环境变量PS2存储命令行的换行符。
2.4 预定义变量
- 预定义变量的概念:预定义变量是由shell程序提供的内置变量,用来存储shell程序运行过程中的状态信息,无需设置,只能引用。
- 预定义变量的使用:变量$$存储当前进程的进程号信息;变量$0存储当前进程的进程名信息;变量$?存储当前命令的返回值信息(0代表成功,非0代表失败);变量$!存储最近一个后台进程的进程号信息。
2.5 位置变量
- 位置变量的概念:位置变量是由shell程序提供的变量,可用来引用传递给程序的参数;位置变量通过该程序参数在传递给程序时的位置顺序来引用。
- 位置变量的使用:位置变量$1, $2, ……,$9(eg:. test.txt $1路径值 $2路径值);位置变量的切取用命令shift。eg:下图中的$1被切掉了,$2变成了$1,$3变成了$2。
3.管道与重定向
3.1 标准设备文件
标准输入文件:stdin
- 标准输入的设备文件为/dev/stdin
- 对应的文件描述符为“0”
标准输出文件:stdout
- 标准输出的设备文件为/dev/stdout
- 对应的文件描述符为“ i ”
标准错误文件:stderr
- 标准错误的设备文件为/dev/stderr
- 对应的文件描述符为“ 2 ”
3.2 管道
管道的概念
- 管道是系统提供的供命令间传递信息的设备
- 管道的信息传递是由前往后单向的传递
- 管道仅将前一道命令程序的标准输出传递给后一命令
管道的使用
- shell中使用管道符 “ | ”来进行管道操作。eg:ps aux | grep “bash”
管道的级联
- 管道符允许被多级使用,即管道的级联。eg:ps aux | grep "bash" | grep -v "grrep"
3.3 重定向
重定向的概念
- 重定向是指将原本关联输入或输出到标准设备文件的信息重新定向到指定的磁盘文件的举措。
输出重定向的使用
- 标准输出重定向:eg:ls -l test.* >output.txt (覆盖重定向);eg:ls -l test.* >>output.txt(追加重定向)
- 标准出错重定向:eg:ls -l test.* 2>output.txt (覆盖重定向,文件不存在会创建);eg:ls -l test.*2 >>output.txt(追加重定向)
输入重定向的使用
- 标准输入重定向:eg:cat <output.txt
- 标准输入重定向之here document技术:eg:cat <<EOF … EOF(结束标识符)
合并输出重定向的使用
- 合并重定向是指合并标准输出和标准错误的信息输出
- 使用合并重定向符“&”即可实现合并输出:eg:ls -l test.* filenotfound &>output.txt(如果不加&,会清空文件再合并,如果出错,文档就成空的了;如果把&换成2,会把出错信息保留,正确信息被清空。此处也可用>>追加)
3.4 管道与重定向的应用
管道过滤信息的重定向输出
- 综合使用管道符与重定向符能实现命令使用的最大灵活性,以满足应用需求。eg:ls -l | grep new >output.txt(筛选出的内容被存到output.txt中)
利用重定向拷贝文件
- 综合使用输入输出的重定向符,可以实现简单的cp命令的功能。eg:cat <output.txt >output2.txt (复制到output2.txt中,如果目标文件不存在会被创建)
here document使用
- here document输入重定向技术再实际工作中有广泛的应用。eg:cat <<FF (以FF结尾)eg:cat >output3.txt <<FF(文件的内容会输入到output3.txt中)
4.Shell脚本
4.1 脚本的概述
脚本的概念
- 脚本是指以解释执行方式的程序语言集合体(解读一条语句,执行一条语句)
- 狭义的脚本即指脚本文件
脚本的用途
- 批量的顺序处理命令语句以实现命令应用需求
- 非交互式的命令使用方式可以提升命令执行的效率
脚本的使用
- 脚本文件的合法编写是脚本使用的程序基础
- 脚本文件的正确执行是脚本使用的运行实例(eg:. test.sh eg:./test.sh eg:/home/test.sh)
4.2 脚本的控制结构
控制结构的概念
- 程序的控制结构使得程序语句的执行顺序能有条件的智能改变
- 控制结构有顺序结构、分支结构和循环结构
顺序结构的概念
- 顺序结构是指按照语句的顺序从上至下依次执行
- 脚本中的顺序结构,通常语句前后没有制约关系
name$ vim test.sh
#!/bin/bash //脚本的声明语句,后面的脚本由它执行
ls -l /home
echo "hello world."
echo $0 $$
name$ . test.sh //直接在当前shell下执行
name$ chmod u+x test.sh //加可执行权限
name$ ./test.sh //在test.sh下执行
分支结构
- 分支结构根据条件判断的真假来选择执行某一分支的语句体
- 分支结构的实现方式:$$ 、||符号级联;if-else语句;case语句
name$ vim test.sh
#!/bin/basg
#顺序结构
test -x test01.sh && echo "ok" || echo "failure"
#if-else结构
if [ -x test2.sh ]
#如果条件为真
then
echo "OK"
#否则如果次要条件满足
elif [ -x $2 ];then
echo "$2 executable"
#如果条件为假
else
echo "fail"
#结束
fi
#case结构
#赋值不加空格
Value=$3
case $Value in
a)
echo "A"
;;
b)
echo "B"
;;
*)
echo "C"
;;
#结束
esac
name$ . test.sh a.sh b.sh q
循环结构
- 循环结构根据条件判断的真假来确定是否执行循环体内的雨具
- 循环结构的实现方式:while语句;until语句;for-in语句
name$ vim test2.sh
#!/bin/bash
Count=1
#当$1有可执行权限时,执行do
while [ -x $1 ]
do
#当count大于等于5时,退出循环
[ $Count -ge 5 ] && break
echo "running"
let Count++
done
Count=1
#当$2没有可执行权限时,执行do
until [ -x $2 ]
do
#当count大于等于5时,退出循环
[ $Count -ge 5 ] && break
echo "running"
let Count++
done
Count=1
#当循环次数不超过var的次数,执行do,此处需要执行五次
for Var in aa bb cc dd oo pp
do
echo "loop $Count"
echo "running"
let Count++
done
name$ chmod u+x test2.sh
name$ . test2.sh test.sh
4.3 脚本的使用示例
脚本程序需求
- 从给定的自然数开始,循环输出10个数,其皆为3的倍数
脚本实现要求
- 程序设计中包含输入的友好提示和对于输入合法性的验证判断
分析
- 输出:输出10个数,皆为3的倍数。
- 输入:某个给定的自然数。
- 处理:1.接受输入,输入要包含友好的输入提示,包含合法性检查;2.筛选出10个数:从给定自然数开始,至满十个3的倍数结束。3.输出要人性化。
name$ vim test3.sh
#!/bin/bash
#----------------------------------
#--从给定的自然数开始,选出10个3的倍数
#----------------------------------
#--输入
read -p "请输入一个自然数:" Input
if [ $Input -gt 0 ] ;then
echo "您输入是自然数,从此自然数开始,10个3的倍数为:"
else
echo "您输入不自然数,程序异常退出。"
exit
fi
#--处理并输出
Count=0
Num=$Input
while [ $Count -lt 10 ]
do
let Num2=$Num%3
if [ $Num2 -eq 0 ];then
echo "$Num"
let Count++
fi
let Num++
done
5.Shell脚本的高级主题
5.1 Shell函数
Shell函数的两种表达形态
- 表达形态一:函数名() ;eg:hello() { echo "hello world"}
- 表达形态二:function 函数名() ; eg:function hello() { echo "hello world" }
Shell函数的使用
- Shell函数使用时只需书写函数名即可,eg:hello
name$ vim test3.sh
#!/bin/bash
hello()
{
echo "hello world."
}
function bye()
{
echo "Bye-bye"
}
hello
bye
name$ . test3.sh
hello world.
Bye-bye
Shell函数的参数传递
- Shell脚本的函数参数依靠位置变量来传递
//例子
function hello() {
echo "$1 你好"
}
- Shell脚本的函数参数传递时按顺序书写在函数名的后面即可;eg:hello world
name$ vim test3.sh
#!/bin/bash
hello()
{
echo "hello $1."
}
function bye()
{
echo "Bye-bye $1"
}
hello "beauty $1"
bye Hua
name$ . test3.sh world
hello beauty world.
Bye-bye Hua
5.2 Shell变量的替换
缺省替换:${Var:-value}(临时替换,不改变变量值)
- 若Var变量未被设置,则临时设置为value。eg:${Day:-Sun}
强制替换:${Var:+value}(临时替换,不改变变量值)
- 若Var变量已被设置,则临时设置值为value。eg:${Day:+Mon}
缺省赋值替换${Var:=value}
- 若Var变量未被设置,则永久设置为value,eg:${Today:=Sun}
缺省错误替换${Var:?string}
- 若Var变量未被设置,则错误输出为string,eg:${Torrow:?"日期错误"}
单次匹配替换${Var/pattern/string}(临时替换,不改变变量值)
- 若Var变量匹配pattern存在,则单次替换输出为string,eg:${Session/Yes/yes}
全局匹配替换${Var//pattern/string}(临时替换,不改变变量值)
- 若Var变量匹配pattern多次,则全部替换输出为string
6.实现猜拳游戏的脚本设计
需求:
- 用脚本实现石头剪刀布的小游戏,用石头、剪刀和布PK,三局两胜。
设计:
- 循环接收用户的“出招”输入;
- 比较判断胜方为电脑还是用户,并输出胜方;
- 统计胜利次数,率先赢得两次,即最终获胜。
核心问题:
- 对赢的判断:每一回合剪刀(J)赢布(B);布(B)赢石头(S);石头(S)赢剪刀(J);三回合比赛,三局两胜
- 每一回合比赛设计流程:用户出招(输入);电脑出招(随机);两类出招比较;判断输赢
name$vim game.sh
#!/bin/bash
#------------------------------
#--剪刀、石头和布的游戏脚本实例--
#------------------------------
Input()
{
while :
do
#clear;echo " --剪刀、石头和布游戏--"
echo "请选择输入剪刀(J)、石头(S)或布(B)"
read Choice
case $Choice in
J|j)
echo -n "您选择的是\"$Choice\"剪刀,"
userChoice=0
break
;;
S|s)
echo -n "您选择的是\"$Choice\"石头,"
userChoice=1
break
;;
B|b)
echo -n "您选择的是\"$Choice\"布匹,"
userChoice=2
break
;;
*)
echo "您的输入不正确,请重新输入!"
sleep 1
;;
esac
done
}
function Judge()
{
let Num=$RANDOM%3
[ $Num -eq 0 ] && echo "电脑选择的是\"J\"剪刀"
[ $Num -eq 1 ] && echo "电脑选择的是\"S\"石头"
[ $Num -eq 2 ] && echo "电脑选择的是\"B\"布匹"
let ${User:=0}; let ${Comp:=0}
if [ $1 -eq $Num ];then
echo "本局平局!"
elif [ $1 -eq 0 ];then
if [ $Num -eq 2];then
echo "本局你赢!" ;let User++
else
echo "本局你输!" ;let Comp++
fi
elif [ $Num -eq 0 ];then
if [ $1 -eq 2 ];then
echo "本局你输!" ;let Comp++
else
echo "本局你赢!" ;let User++
fi
elif [ $1 -gt $Num ]; then
echo "本局你赢!";let User++
else
echo "本局你输!";let Comp++
fi
}
#-- main program --
clear;echo "欢迎来到剪刀、石头和布游戏!"
sleep 2;user=0;Comp=0;Round=1
while [ $Round -le 3 ]
do
sleep 2;clear
echo ">> 剪刀、石头和布第$Round回合比赛 <<"
Input
Judge $userChoice
let Round++
[ $User -ge 2 ] && echo "恭喜,你赢得了整个比赛!"\
&& exit
[ $Comp -ge 2 ] && echo "遗憾,电脑赢得了整个比赛!"\
&& exit
done
if [ $User -gt $Comp ];then
echo "恭喜,你赢得了整个比赛!"
elif [ $Comp -gt $User ];then
echo "遗憾,电脑赢得了整个比赛!"
else
echo "不错,你平了整个比赛。"
fi