5. bash基础以及shell编程初步
一. bash特性以及bash脚本编程初步
bash的特性:
命令行展开:~,{}
命令别名: alias ,unalias
命令历史:history
文件名通配:glob
快捷键:Ctrl + a,e,k,l
命令补全:tab
bash的特性之:命令bash
缓存此前命令的查找结果,命令hash:当执行一个命令的时候开始不是先在path环境变量中找相应的命令,而是先在缓存中查找。
[root@myEcs etc]# hash //命令hash hits command 1 /usr/bin/file 1 /usr/bin/cat 4 /usr/bin/ls //命令查找了两次 [root@myEcs etc]#
选项:
-d:忘记一个命令的缓存
[root@myEcs etc]# hash hits command 1 /usr/bin/file 1 /usr/bin/head 1 /usr/bin/cat 4 /usr/bin/ls [root@myEcs etc]# hash -d file [root@myEcs etc]# hash hits command 1 /usr/bin/head 1 /usr/bin/cat 4 /usr/bin/ls [root@myEcs etc]#
-r:清空缓存
[root@myEcs etc]# hash hits command 1 /usr/bin/head 1 /usr/bin/cat 4 /usr/bin/ls [root@myEcs etc]# hash -r [root@myEcs etc]# hash hash: hash table empty [root@myEcs etc]#
bash特性之:变量
程序:数据+指令
指令:由程序文件提供
数据:IO设备,文件,管道,变量。
程序:算法+数据结构
变量赋值:name=value
变量类型: 存储格式,表示数据范围,参与的运算
编程语言:
强类型变量
弱类型变量:bash吧所有变量统统视为字符串;bash不支持浮点类型
bash中的变量无须事先声明
变量替换:把变量名出现的位置替换为其所指向的内存空间中的数据
变量引用:$(var_name),$var_name
变量名:变量名只能包含字母数字下划线,而且不能以数字开头
变量名:见名知义,驼峰法则。
bash的变量类型:
本地变量:作用域范围仅仅为当前shell进程
环境变量:作用域为当前shell进程及其子进程
局部变量:作用域仅仅为当前某代码片段(函数上下文)
位置参数变量:向执行脚本的shell进程传递参数
特殊变量:shell内置的有特殊用处的变量。
$?:保存执行命令的执行状态结果。
0:成功
1-255:失败
本地变量:
变量赋值:name=value
变量引用:$(name),$name
" ":变量会替换为其值
' ' :变量名不会替换为其值
查看变量:set
撤销变量:uset name
[root@myEcs etc]# name=huangxiaojun [root@myEcs etc]# unset name [root@myEcs etc]# echo $name [root@myEcs etc]#
环境变量:
变量赋值:
(1)export name=value
(2)name=value
export name
(3)declare -x name=value // 内嵌命令,声明环境变量
(4)name=value
declare -x
变量引用:$(name),$name
注意:bash内嵌了许多环境变量(变量名为大写字符),用于定义bash的工作环境
查看环境变量:export ,declare -x,printenv,env
撤销环境变量:unset name
只读变量:
(1) declare -r
(2)readonly name
[root@myEcs etc]# name=huangxiaojun // 定义一个变量 [root@myEcs etc]# declare -r name // 将这个变量设置成只读变量 [root@myEcs etc]# name=wangwu // 变量不能修改 -bash: name: readonly variable // 变量不能撤销 [root@myEcs etc]# unset name -bash: unset: name: cannot unset: readonly variable [root@myEcs etc]#
注意:只读变量无法重新赋值,并且无法撤销;存活的时间为当前shell的进程的生命周期,随shell进程终止而终止
bash特性之多命令执行:
~]# COMMAND; COMMAND2; COMMAND3; ...
逻辑运算:
运算数:真(true,yes,on,1)
假(false,no,off,0)
与:
1 && 1 = 1
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0
或:
1 || 1 = 1
1 || 0 = 1
0 || 1 = 1
0 || 0 = 0
非:
!1 = 0
!0 = 1
短路机制:
~]# COMMAND1 && COMMAND2
如果COMMAND1为“假”,则COMMAND2不执行;如果COMMAND1为“真”,则COMMAND2必须执行。
[root@myEcs tmp]# touch a.txt && touch b.txt // 与运算中,命令1执行成功,那么命令2就执行 [root@myEcs tmp]# ls a.txt b.txt [root@myEcs tmp]#
[root@myEcs tmp]# ls /tmp/c.txt && touch c.txt // 与运算中,第一个命令结果为假 ,则后面命令不执行 ls: cannot access /tmp/c.txt: No such file or directory [root@myEcs tmp]# ls [root@myEcs tmp]#
~]# COMMAND1 || COMMAND2
如果COMMAND1为“真”,则COMMAND2不执行;如果COMMAND1为“假”,则COMMAND2必须执行。
[root@myEcs tmp]# id user1 || useradd user1 // 或运算中,如果第一个结果为假,则执行第二个 id: user1: no such user [root@myEcs tmp]# id user1 uid=1007(user1) gid=1008(user1) groups=1008(user1)
[root@myEcs tmp]# id user1 || userdel user1 // 或运算中,第一个执行为真,后面就不执行 uid=1007(user1) gid=1008(user1) groups=1008(user1) [root@myEcs tmp]# id user1 uid=1007(user1) gid=1008(user1) groups=1008(user1) [root@myEcs tmp]#
shell标本编程的实现:
编程语言的分类:根据运行方式
编译运行:源代码-->编译器(编译)-->运行二进制程序文件
解释运行:源代码-->运行时启动解释器,由解释器边解释边运行。
编程模型:面向过程,面向对象
如何写shell脚本:
脚本文件的第一行,定格,给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
常见的解释器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
运行脚本:
(1) 赋予执行权限,直接运行此程序文件。
chmod +x myfirst.sh
(2) 直接运行解释器,将脚本命令行参数传递给解释器程序。
bash myfirst.sh
练习1:写一个脚本,实现如下功能。
(1)显示/etc目录下所有以大写p或小写p开头的文件或目录本身
(2)显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换成大写后显示
(3)创建临时文件/tmp/myfile.XXXXXX。
#!/bin/bash ls /etc/[pP]* ls /var/* | tr 'a-z' 'A-Z' mktemp /tmp/myfile.XXXXXX
bash的配置文件:
两类:
profile类:为交互式登录的shell进程提供配置
bashrc类:为非交互式登录的shell进程提供配置
登录类型:
交互式登录shell进程:
直接通过某终端输入账号和密码后登录打开的shell进程
使用su命令:su - USERNAME ;或者使用su -l USERNAME执行的登录切换
非交互式登录shell进程:
su USERNAME执行的用户登录切换。
图形界面下打开的终端。
运行脚本的时候
frofile类:
全局配置:对所有用户都生效
/etc/frofile
/etc/profile.d/*.sh
用户个人:仅仅对当前用户有效
/home/.bash_profile
公用:
1. 用于定义环境变量
2. 运行命令或脚本
bashrc类:
全局:
/etc/bashrc
用户个人:
/home/.bashrc
公用:
1. 定义本地变量
2. 定义命令别名
注意:仅仅管理员可以修改全局配置文件
启动时要运行的命令或脚本:/etc/profile.d/*.sh
bash脚本编程之算数运算
+ - * / ** %
算数运算格式:
(1)let name=算数运算表达式
[root@myEcs tmp]# declare -i num1=3 [root@myEcs tmp]# declare -i num2=5 [root@myEcs tmp]# echo "$num1 + $num2" 3 + 5 [root@myEcs tmp]# let sum=$num1+$num2 // 方法一 [root@myEcs tmp]# echo $sum 8 [root@myEcs tmp]#
(2)$[算数运算表达式]
[root@myEcs tmp]# echo "$[$num1+$num2]" //方法二 8 [root@myEcs tmp]#
(3)$((算数运算表达式))
[root@myEcs tmp]# echo "$(($num1+$num2))" //方法三 8 [root@myEcs tmp]#
(4)expr $num1 + num2 必须要有空格
变量引用:sum=$(expr $num1 + $num2)
[root@myEcs tmp]# expr $num1 + $num2 //方法四 8 [root@myEcs tmp]# sum=$(expr $num1 + $num2) [root@myEcs tmp]# echo "$sum" 8 [root@myEcs tmp]#
注意:乘法符号在有些场景中需要使用转义符。
练习:
1. 添加三个用户求此三个用户的uid之和
#!/bin/bash userName1=hxjuser1 userName2=hxjuser2 userName3=hxjuser3 id $userName1 > /dev/null || useradd $userName1 > /dev/null id $userName2 > /dev/null || useradd $userName2 > /dev/null id $userName3 > /dev/null || useradd $userName3 > /dev/null uidNum1=`id $userName1 | egrep -o "uid=[[:digit:]]{4,}" |cut -d "=" -f 2` uidNum2=`id $userName2 | egrep -o "uid=[[:digit:]]{4,}" |cut -d "=" -f 2` uidNum3=`id $userName3 | egrep -o "uid=[[:digit:]]{4,}" |cut -d "=" -f 2` echo "sum_uuid=$[$uidNum1+$uidNum2+$uidNum3]" ~
二. bash 脚本编程进阶
脚本文件格式:
第一行,定格:#!bin/bash
注释信息:#
代码注释:
缩进,适度添加空白行;

浙公网安备 33010602011771号