Shell script.
一、Shell介绍
Shell基本上分两大类
图形界面shell
windows Explorer
linux GNOME / KDE等
命令行式shell
windows command.com (MS-DOS系统)
linux bash / sh / ksh / csh 等
IBM AIX ksh
FreeBSD csh
Linux bash
ls /bin/*sh 查看当前系统支持的Shell
cat /etc/shells
交互式shell 等待用户输入命令再执行
非交互式shell 不与用户交互,而是读取存放在文件里的命令,并执行它们
命令行式shell的好处:
当远程联机时,命令行界面传输速度一定比较快,不会出现断线或信息外流的问题,
而且多接触些命令行的东西会让我们更了解Linux
Bash Shell的功能
命令记忆能力
命令与文件补全功能
命令别名设置功能
作业管理,前台后台控制
Shell Scripts的强大功能
通配符
Bash Shell特殊符号
# comment
\ escape, 转义
~ 家目录
| pipe, 管道
>,>> 重定向
<,<< 重定向
& 作业控制
! 逻辑非
/ 路径分割符
"" soft quote, 软引用(一部分特殊符号被当作普通字符,但是$仍然是特殊符号).
'' hard quote, 硬引用(所有的特殊符号被当作普通字符)
`` 命令替换
() 子shell起始和结束(也是命令替换)
{} 命令块组合
; && || 连续命令执行分隔符
* ? [a-z] 通配符
================================================================================
二. 命令如何执行
1. shell命令分类1
内部命令 实现在shell解释器内部的命令
外部命令 文件系统中的可执行文件
2. shell命令分类2
简单命令 单一的执行某个命令
管道 通过管道组合单一命令
命令队列 通过 && || ; & 连接执行的命令.
复合命令 以shell保留字/控制运算符开始, 以shell保留字/控制运算符结束的shell编程结构. 控制运算符: 包括换行符和 || && & ; ;; | |& ( )
协同进程 以保留字coproc开头执行的命令. 和一般命令与父进程同步执行(意即:串行)不同, 协同进程与父进程异步执行. 请参看bash文档.
3. 命令执行流程
1) 以IFS(Internal Field Seperator)将所输入字面量拆分为字段(word).
2) 语法分析. 对复合命令加入控制结构和管道处理等, 分解为简单命令.
3) 进行简单命令扩展.
4) 搜索命令并执行.
4. 简单命令扩展
1) 被解释器当作变量赋值的单词, 将被保存下来以备后续处理.
2) 不是变量赋值会被扩展. 扩展之后, 第一个单词作为命令名称, 其后作为该命令的选项和参数.
3) 进行重定向处理.
4) 每个变量赋值语句中"="后面的文本在赋给变量之前会进行大括号扩展, 参数扩展, 命令替换, 算术
扩展和引用去除.
5. 命令搜索
1) 搜索shell函数.
2) 搜索别名.
3) 搜索内部命令.
4) 搜索$PATH.
================================================================================
三. 条件判断
1. shell以命令退出状态为条件判断依据. 退出状态0为true, 非0为false.
2. 条件控制结构:
if condition; then
cmd
fi
if condition
then
cmd
fi
if condition
then
cmd1
else
cmd2
fi
if condition1
then
cmd1
elif condition2
then
cmd2
...
else
cmd
fi
3. condition:
任意命令的退出状态.
最常用的为 [ 或者test 命令:
与文件存在与否的判断
-e 是否存在
-f 是否为普通文件
-d 是否为目录
-s 是否为空的文件
-p 是否为管道文件
-b 是否为块设备文件
-c 是否为字符设备文件
-L 是否为软链接
-S 是否Socket文件
与文件权限有关的判断
-r 是否有可读的权限
-w 是否有可写的权限
-x 是否有可执行权限
-u 是否有特权位
-g 是否有组特权位
-k 是否有t位,即粘贴位
两个文件的比较判断
-nt 比较file1比file2新
-ot 比较file1比file2旧
-ef 比较file1和file2是否为同一个文件,一般用于判断硬链接
整数之间的大小判断
-eq 相等
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
字符串之间的判断
-z 是否为空字符串
-n 是否为非空字符串
str1 = str2 是否相等
str1 != str2 是否不等
多重条件判断
-a 两个条件同时满足,就为真,相当于and
-o 两个条件满足其一,就为真,相当于or
如果使用 [[ ]], 则多重判断可以使用:
[[ xxx && xxx || xxx ]] 的形式.
================================================================================
test ===[ ]
[[ ]] 可用逻辑运算
四. 算术运算
算术运算和if判断是不同的, 算术中以非0为真, 0为假.
id++ id--
++id --id
- +
! ~
**
* / %
+ -
<< >>
<= >= < >
== !=
&
^
|
&&
||
cond ? expr1 : expr2
= *= /= %= += -= <<= >>= &= ^= |=
expr1, expr2
let a++ 支持数学运算让a自加1
let 'a+=3' 数学运算a=a+3
c=$[a+5] 让变量a的值加5赋给c
d=$((a+7)) 让变量a的值加上7再把结果赋给变量d
f=`expr $a / 3` 支持运算并把结果给变量f
expr的用法:
ARG1 | ARG2 若ARG1 的值不为0 或者不为空,则返回ARG1,否则返回ARG2
ARG1 & ARG2 若两边的值都不为0 或不为空,则返回ARG1,否则返回 0
ARG1 < ARG2 ARG1 小于ARG2
ARG1 <= ARG2 ARG1 小于或等于ARG2
ARG1 = ARG2 ARG1 等于ARG2
ARG1 != ARG2 ARG1 不等于ARG2
ARG1 >= ARG2 ARG1 大于或等于ARG2
ARG1 > ARG2 ARG1 大于ARG2
ARG1 + ARG2 计算 ARG1 与ARG2 相加之和
ARG1 - ARG2 计算 ARG1 与ARG2 相减之差
ARG1 * ARG2 计算 ARG1 与ARG2 相乘之积
ARG1 / ARG2 计算 ARG1 与ARG2 相除之商
ARG1 % ARG2 计算 ARG1 与ARG2 相除之余数
字符串 : 表达式 定位字符串中匹配表达式的模式
match 字符串 表达式 等于"字符串 :表达式"
substr 字符串 偏移量 长度 替换字符串的子串,偏移的数值从 1 起计
index 字符串 字符 在字符串中发现字符的地方建立下标,或者标0
length 字符串 字符串的长度
+ 记号 将记号解析为字符串,即使它是一个类似"match"或
运算符"/"那样的关键字
( 表达式 ) 表达式的值
================================================================================
五. 循环
for 循环语句
for i in 1 2 3 4 5 6 循环6次
do
循环体
done
for ((i = 0; i < 9; i++)) C语言风格循环9次,定义变量i,i < 9为循环退出条件,i++代表每循环一次自加一次,1到5的循环
do
循环体
done
for ((i = 10; i > 0; i--)) C语言风格,循环10次,i自减式循环,10到1的循环
do
循环体
done
for i in `seq 100` 产生1到100的序列循环
do
循环体
done
for i in `seq 10 50` 产生10到50序列循环
do
...
done
for i in `seq 1 5 100` 产生1到100序列循环,每次以5增加
do
...
done
for i in `ls /etc/*` 可以把一批文件,作为值循环赋值给变量
do
循环体
done
----------------------------------------------------------------------
until 循环
满足条件就循环结束
使用until写出从1打印到5
a=1
until [ $a -gt 5 ]
do
echo $a
let a++
done
----------------------------------------------------------------------
while 循环
循环次数不确定,或者是死循环等用while循环
while [ ] 条件为真循环
do
done
死循环两种
while true
do
done
while :
do
done
----------------------------------------------------------------------
常用脚本控制内部命令
exit 退出脚本
return 退出函数
break 退出循环
continue 跳过此次循环
sleep 延时
随机数
echo $RANDOM 产生随机数
set | grep RANDOM 查看最后一次产生的随机数
产生0到1的随机数
echo $((RANDOM % 2))
echo $[RANDOM % 2]
产生0到100随机数
echo $[RANDOM % 101]
产生50到150的随机数
echo $[RANDOM % 101 + 50]
----------------------------------------------------------------------
菜单case select
case "$1" in 获得变量值
a) 如果变量值等于a,执行下面echo A
echo A
;;
b)
echo B
;;
c)
echo C
;;
*)
echo D
exit 1
esac
例:
敲一个键,判断是大写字母,小写字母,还是数字或其它
[:alnum:] 字母数字
[:blank:] 空格或者制表符
[:digit:] 纯数字
[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点符号
read -n 1 -p "hit a key on your keyboard: " key
case "$key" in
[[:lower:]])
echo "lowercase letter"
;;
[[:upper:]])
echo "uppercase letter"
;;
[0-9])
echo "number"
;;
*)
echo "others"
esac
输入一个人名,选择性别boy girl
case "$sex" in
B|b)
echo boy
;;
G|g)
echo girl
;;
*)
echo "invalid select!!"
select 建立菜单的另一种工具,它是从ksh引进的
PS3="" PS3是select命令用来加入提示字符串的环境变量(默认使用的提示符为#?)
select var in a b c d...
do
代码段
done
例
PS3="Please input : "
select os in xp vista windows7 linux unix
do
echo
echo "your select system is : $os"
echo
break
done
----------------------------------------------------------------------
数组
数组没有类型,里面的元素也是可以任意类型
数组的定义方式一
a=(1 2 3 a b c "hello world") 定义a数组,只能使用数字下标去访问元素
数组的定义方式二
arr[3]="hi" 定义数组,可以不连续
arr[0]="com"
arr[4]="boay"
数组的定义方式三
arr=([0]="he" [1]="hi" [2]=123)
数组元素的访问
echo ${a[0]} 打印结果为1,访问第一个元素
echo ${a[3]} 访问第四个元素,打印结果为a
echo ${a[6]} 访问第六个元素,打印结果为hello world
获取数组元素的个数
echo ${#a[*]}
输出所有元素
echo ${a[*]}
echo ${a[@]}
数组的复制
b=(${a[*]})
----------------------------------------------------------------------
函数
定义方式
function fun_name () {
...
}
function_name () {
...
}
例
choice () {
PS3="Please input : "
select os in xp vista windows7 linux unix
do
echo
echo "your select system is : $os"
echo
break
done
return 3
}
choice 调用函数
echo $? 得到函数的返回值
----------------------------------------------------------------------
================================================================================