shell编程基础之二
算数运算
bash中的算术运算:help let
- +, -, *, /, %取模(取余), **(乘方),乘法符号有些场景中需要转义
- 实现算术运算:
- (1) let var=算术表达式
- (2) var=$[算术表达式]
- (3) var=$((算术表达式))
- (4) var=$(expr arg1 arg2 arg3 ...)
- (5) declare –i var = 数值
- (6) echo ‘算术表达式’ | bc
bash有内建的随机数生成器变量:$RANDOM(0-32767)
- 示例:生成 0 - 49 之间随机数
- echo $[$RANDOM%50]
赋值
增强型赋值:
- +=, -=, *=, /=, %=
let varOPERvalue
- 例如:let count+=3
- 自加3后自赋值
自增,自减:
- let var+=1
- let var++
- let var-=1
- let var--
逻辑运算
true, false
- 1, 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 ! true
- ! 0 = 1 ! false
异或:^
- 异或的两个值,相同为假,不同为真
短路运算
- 短路与
- 第一个为0,结果必定为0
- 第一个为1,第二个必须要参与运算
- 短路或
- 第一个为1,结果必定为1
- 第一个为0,第二个必须要参与运算
条件测试
判断某需求是否满足,需要由测试机制来实现专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
- 若真,则返回0
- 若假,则返回1
测试命令:
- test EXPRESSION
- [ EXPRESSION ]
- [[ EXPRESSION ]]
- 注意:EXPRESSION前后必须有空白字符
bash的数值测试
-v VAR
- 变量VAR是否设置
- 示例:判断 NAME 变量是否定义
- [ -v NAME ]
数值测试:
- -gt 是否大于
- -ge 是否大于等于
- -eq 是否等于
- -ne 是否不等于
- -lt 是否小于
- -le 是否小于等于
bash的字符串测试
字符串测试:
- -z "STRING" 字符串是否为空,空为真,不空为假
- -n "STRING"字符串是否不空,不空为真,空为假
- = 是否等于
- > ascii码是否大于ascii码 < 是否小于
- != 是否不等于
- == 左侧字符串是否和右侧的PATTERN相同
- 注意:此表达式用于[[ ]]中,PATTERN为通配符
- =~ 左侧字符串是否能够被右侧的PATTERN所匹配
- 注意: 此表达式用于[[ ]]中;扩展的正则表达式
bash的文件测试
存在性测试
- -a FILE:同 -e
- -e FILE: 文件存在性测试,存在为真,否则为假
存在性及类别测试
- -b FILE:是否存在且为块设备文件
- -c FILE:是否存在且为字符设备文件
- -d FILE:是否存在且为目录文件
- -f FILE:是否存在且为普通文件
- -h FILE 或 -L FILE:存在且为符号链接文件
- -p FILE:是否存在且为命名管道文件
- -S FILE:是否存在且为套接字文件
bash的权限测试
文件权限测试:
- -r FILE:是否存在且可读
- -w FILE: 是否存在且可写
- -x FILE: 是否存在且可执行
文件特殊权限测试:
- -u FILE:是否存在且拥有suid权限
- -g FILE:是否存在且拥有sgid权限
- -k FILE:是否存在且拥有sticky权限
bash的文件属性测试
文件大小测试:
- -s FILE: 是否存在且非空
文件是否打开:
- -t fd: fd 文件描述符是否在某终端已经打开
- -N FILE:文件自从上一次被读取之后是否被修改过
- -O FILE:当前有效用户是否为文件属主
- -G FILE:当前有效用户是否为文件属组
双目测试:
- FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
- FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
- FILE1 -ot FILE2: FILE1是否旧于FILE2
bash的组合测试条件
第一种方式:
- [ EXPRESSION1 -a EXPRESSION2 ] 并且
- [ EXPRESSION1 -o EXPRESSION2 ] 或者
- [ ! EXPRESSION ] 取反
- -a 和 -o 需要使用测试命令进行,[[ ]] 不支持
第二种方式:
- COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN
- COMMAND1 || COMMAND2 或者,短路或,代表条件性的OR ELSE
- ! COMMAND 非
- 示例:
- [ -f “$FILE” ] && [[ “$FILE”=~ .*.sh$ ]]
条件性的执行操作符
示例:
#grep -q no_such_user /etc/passwd || echo 'No such user'
- No such user
#ping -c1 -W1 172.16.0.1 &> /dev/null \
> && echo '172.16.0.1 is up' \
> || (echo '172.16.0.1 is unreachable'; exit 1)
- 172.16.0.1 is up
示例:
test "$A" = "$B" && echo "Strings are equal"
test "$A"-eq "$B" && echo "Integers are equal"
[ "$A" = "$B" ] && echo "Strings are equal"
[ "$A" -eq "$B" ] && echo "Integers are equal"
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
[ -z "$HOSTNAME" -o $HOSTNAME = "localhost.localdomain" ] \
>&& hostname www.magedu.com
用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N -d ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
read -p “Enter a filename: “ FILE
条件选择if语句
选择执行:
- 注意:if 语句可嵌套
#单分支
if 判断条件;then
条件为真的分支代码
fi
#双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
#多分支
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
else
以上条件都为假的分支代码
fi
#逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
条件判断case语句
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
*)
默认分支
;;
esac
case支持glob风格的通配符:
- *: 任意长度任意字符
- ?: 任意单个字符
- []:指定范围内的任意单个字符
- a|b:
bash如何展开命令行
- 把命令行分成单个命令词
- 展开别名
- 展开大括号的声明({}
- 展开波浪符声明(~)
- 命令替换$() 和 ``)
- 再次把命令行分成命令词
- 展开文件通配(*、?、[abc]等等)
- 准备I/0重导向(<、>)
- 运行命令
防止扩展
反斜线(\)会使随后的字符按原意解释
- echo Your cost: $5.00
- Your cost: $5.00
加引号来防止扩展
- 单引号(’’)防止所有扩展
- 双引号(”“)也可防止扩展,但是以下情况例外:
- $(美元符号) 变量扩展
- ` ` (反引号) 命令替换
- \(反斜线) 禁止单个字符扩展
- !(叹号) 历史命令替换
bash的配置文件
按生效范围划分,存在两类:
- 全局配置:
- /etc/profile
- /etc/profile.d/*.sh
- /etc/bashrc
- 个人配置:
- ~/.bash_profile
- ~/.bashrc
shell登陆的两种方式
交互式登录:
- (1)直接通过终端输入账号密码登录
- (2)使用“su - UserName” 切换的用户
- 执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录:
- (1)su UserName
- (2)图形界面下打开的终端
- (3)执行脚本
- (4)任何其它的bash实例
- 执行顺序: /etc/profile.d/*.sh --> /etc/bashrc -->~/.bashrc
profile类和bashrc类
按功能划分,存在两类:
- profile类和bashrc类
profile类:为交互式登录的shell提供配置
- 全局:/etc/profile, /etc/profile.d/*.sh
- 个人:~/.bash_profile
- 功用:
- (1) 用于定义环境变量
- (2) 运行命令或脚本
bashrc类:为非交互式和交互式登录的shell提供配置
- 全局:/etc/bashrc
- 个人:~/.bashrc
- 功用:
- (1) 定义命令别名和函数
- (2) 定义本地变量
编辑配置文件生效
修改profile和bashrc文件后需生效
- 两种方法:
- 重新启动shell进程
- . 或source Conf_File_Name
- 例: . ~/.bashrc
bash退出任务
保存在~/.bash_logout文件中(用户)
在退出登录shell时运行
用于
- 创建自动备份
- 清除临时文件
set命令
$- 变量
- h:hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭
- i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的shell。所谓的交互式shell,在脚本中,i选项是关闭的
- m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
- B:braceexpand,大括号扩展
- H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令
脚本安全
- -u 在扩展一个没有设置的变量时,显示错误信息等同set -o nounset
- -e 如果一个命令返回一个非0退出状态值(失败)就退出等同set -o errexit