bash脚本编程基础
- 脚本文件格式
- 第一行顶格写脚本的解释器路径,例如bash脚本需要写:#!/bin/bash
- 第二行写描述:# description: say hello
- 第三行写版本:# version: 1.0.0
- 第四行写作者:# author: Jerry <Jerry@whitehouse.gov>
- 第五行写日期:# date: 2017-10-23
- 要写代码注释:#
- 缩进,适度添加空白行
- 语言:编程语法格式,库,算法和数据结构
- 编程思想
- 问题空间:自然语言
- 解空间:编程语言
- 在两种空间之间切换
- 变量
- 局部变量
- 本地变量
- 环境变量
- 位置参数变量
- 特殊变量
- 数据类型
- 字符型
- 数值型
- shell脚本是一种弱类型的编程语言:所有的数据类型都当作字符类型
- 算术运算
- +,-,*,/,%
- let var=expression
- var=$[expression]
- var=$((expression))
- var=$(expr argu1 argu2 argu3)
- 注:有些时候乘法符号*需要转义
- 增强型赋值
- +=,-=,*=,/=,%=,++,--
- let i+=1,前面一般要加let
- var = $[$var + 1]; let var+=1; let var++
例子:添加两个用户,并求出他们的id之和
执行脚本的方式:bash File_Name
练习1:编写一个脚本,计算/etc/passwd文件中第10个用户和第20个用户的id号之和
id1 = $(head -10 /etc/passwd | tail -1 | cut -d: -f3)
id2 = $(head -20 /etc/passwd | tail -1 | cut -d: -f3)
练习2:编写一个脚本,计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和
grep "^[[:space:]]*$" /etc/rc.d/init.d/functions | wc -l
- 条件测试
- 判断某需求是否满足,需要由测试机制来实现
- 如何编写测试表达式以实现所需的测试
- 执行命令,并利用命令的状态返回值来判断
- 0:成功
- 1-255:失败
- 测试表达式
- test EXPRESSION
- [ EXPRESSION ]:表达式和中括号之间必须要有空格,否则为语法错误
- [[ EXPRESSION ]]:表达式和中括号之间必须要有空格,否则为语法错误
- 执行命令,并利用命令的状态返回值来判断
- bash的测试类型
- 数值测试:数值比较
- -eq:是否等于,例如:[ $num1 -eq $num2 ]
- -ne:是否不等于
- -gt:是否大于
- -ge:是否大于等于
- -lt:是否小于
- -le:是否小于等于
- 字符串测试:
- ==:是否等于
- >:是否大于
- <:是否小于
- !=:是否不等于
- 以上按照ascII码比较
- =~:左侧的字符串是否能够被右侧的模式所匹配
- -z "STRING":判断指定的字串是否为空
- -n "STRING":判断指定的字串是否不空
- 注意:
- 字符串比较表达式尽可能的定义在双中括号中,单中括号有时候会无效
- 字符串要加引用,防止null;不做变量替换时双引号单引号都行,做替换时用双引号
- 文件测试
- 存在性测试
- -a File
- -e File
- 以上两个含义一样,存在则为真,否则则为假
- 例如:[ -e /etc/rc.d/rc.sysinit ],然后echo $?
- 存在性及类型测试
- -b File:表示是否存在并且为块设备文件
- -c File:表示是否存在并且为字符设备文件
- -d File:表示是否存在并且为目录文件
- -f File:表示是否存在并且为普通文件
- -h FIle或者-L File:表示是否存在并且为符号链接文件
- -p File:表示是否存在并且为命名管道文件
- -S File:表示是否存在并且为套接字文件
- 存在性及权限测试
- -r File:表示是否存在并且对当前运行脚本的用户可读
- -w File:表示是否存在并且对当前运行脚本的用户可写
- -x File:表示是否存在并且对当前运行脚本的用户可执行
- 以下是特殊权限测试:
- -u File:表示是否存在并且对当前运行脚本的用户具有suid权限
- -g File:表示是否存在并且对当前运行脚本的用户具有sgid权限
- -k File:表示是否存在并且对当前运行脚本的用户具有sticky权限
- 存在性及是否有内容测试
- -s File:表示是否存在并且非空
- 存在性及时间戳测试
- -N File:表示是否存在并且自从上一次读取后是否被修改过
- 存在性及从属关系测试
- -O File:表示是否存在并且当前运行脚本的用户是否为文件的属主
- -G File:表示是否存在并且当前运行脚本的用户是否属于文件的属组
- 双目测试
- File1 -ef File2:File1与File2是否为指向同一个文件系统的相同inode的硬链接
- File1 -nt File2:File1是否新于File2
- File1 -ot File2:File1是否旧于File2
- 存在性测试
- 组合测试条件
- 逻辑运算
- 第一种方式
- COMMAND1 && COMMAND2
- COMMAND1 || COMMAND2
- !COMMAND
- 例子:[ -O File ] && [ -r File ]:拥有且可读
- 第二种方式
- EXPRESSION1 -a EXPRESSION2:参考上面,可以单中括号整个扩起来,也是双中括号,也可以test
- EXPRESSION1 -o EXPRESSION2
- !EXPRESSION
- 例子:[ -O File -a -x File ]:拥有且可执行
- 第一种方式
- 练习:将当前主机名称保存至hostName变量中
- 主机名如果为空,或者为localhost[.localdomain],则将其设置为www.magedu.com
- 答案:
- hostName=$(hostname)
- [ -z "$hostName" -o "$hostName"=="localhost.localdomain" -o "$hostName"=="localhost" ] && hostname www.magedu.com
- 逻辑运算
- 数值测试:数值比较
- 脚本的状态返回值
- 默认是脚本中执行的最后一条命令的状态返回值
- 自定义退出状态码:exit [n],不加数字默认为0
- shell进程遇到exit时,即会终止。因此,整个脚本执行即为结束
- id user3 &> /dev/null && exit 0 || useradd user3 ---该命令表示用户存在则退出,否则添加用户
- 向脚本传递参数
- 利用位置参数变量实现
- 假如有一个脚本myscript.sh,用户运行的时需要给两个参数:myscript.sh argu1 argu2,则脚本内部引用变量的方式为:$1, $2
- $1和$2就叫做位置参数变量
- 两位数以后需要叫花括号,例如${10}, ${11}...
- 轮替:shift #,不指定数字则shift一个
-
- 练习:写一个脚本,通过命令传递两个文本文件路径给脚本,计算其空白行数之和
- 特殊变量
- $0:也是一个位置参数变量,表示脚本文件路径
- $#:脚本参数的个数
- $*:所有参数,每一个参数都当作一个独立的字符串
- $@:所有参数,所有参数合起来做为一个字符串
代码执行顺序:
- 顺序执行:逐条执行
- 选择执行:
- 代码存在一个分支:条件满足时执行
- 两个或以上的分支:只会执行其中一个满足条件的分支
- 单分支写法一:测试条件和then在同一行时,需要加;号
if 测试条件;then
代码分支
fi
-
- 单分支写法二:测试条件和then不在同一行时,不需要加;号
if 测试条件
then
代码分支
fi
-
- 双分支写法:
if 测试条件;then
代码分支
else
代码分支
fi
-
- 示例:通过参数传递一个用户名给脚本,此用户不存在时则添加之,并且设置用户密码同用户名
练习1:通过命令行参数给定两个数字,输出其中的大者
练习2:通过命令行参数给定一个用户名,判断其ID是偶数还是奇数
练习3:通过命令行参数给定两个文件名,如果某文件不存在,则结束脚本执行;否则,返回每个文件的行数,并说明其中行数较多的文件
- 循环执行:代码片段(循环体)要执行0,1或多个来回