shell script编程

[TOC]

shell script (纯文本文件) 在系统管理上是一个好工具, 但是用在处理大量数值运算上就不好了, 因其速度较慢, 且使用CPU资源较多, 容易造成主机资源分配不良.

shell script的执行至少需要 r 权限, 若需要命令执行, 至少需要 rx权限.

​ && 代表and, || 代表or.

​ var=$( 命令 ) 引用命令结果

​ var=$((整数的运算))

​ var=${命令或参数或值}, 变量引用

​ 与一般编程语言不同, 等号左右两边不可分.

0. 判断式

特别要注意一种简单的判断式写法: [ -e $var ] && echo "​$var is existing."

0.1 文件类型

test -e filename 或 [ -e "filename" ]
测试标志 代表意义
-e 文件名是否存在
-f 文件名是否存在且为文件 (file)
-d 文件名是否存在且为目录 (directory)
-b 文件名是否存在且为 bolck device 设备
-c 文件名是否存在且为 character device 设备
-S 文件名是否存在且为 Socket device 设备
-p 文件名是否存在且为 FIFO (pipe) 文件
-L 文件名是否存在且为一个连接文件

0.2 文件权限

test -r filename 或 [ -r "filename" ]
测试标志 代表意义
-r 检测该文件名是否存在且具有"可读"的权限
-w 检测该文件名是否存在且具有"可写"的权限
-x 检测该文件名是否存在且具有"可执行"的权限
-u 检测该文件名是否存在且具有"SUID"的权限
-g 检测该文件名是否存在且具有"SGID"的权限
-k 检测该文件名是否存在且具有"SBIT"的权限
-s 检测该文件名是否存在且为"非空白文件"

0.3 文件比较

test file1 -nt file2 或 [ "file1" -nt "file2" ]
测试标志 代表意义
-nt (newer than) 判断file1是否比file2新
-ot (older than) 判断file1是否比file2旧
-et 判断file1于file2是否为同一文件, 可用在hard link的判定上.
主要意义在于判定两个文件是否均指向同一个inode

0.4 整数判定

test n1 -eq n2 或 [ "n1"  -eq "n2" ]
测试标志 代表意义
-eq equal
-ne not equal
-gt greater than
-lt less than
-ge greater than or equal
-le less than or equal

0.5 字符串

test -z str1 或 [ -z "str1" ]
test str1 == str2 或 [ "str1" != "str2" ]
测试标志 代表意义
-z 判断str1是否为0, 若为空字符串, 则为true
-n 判断str1是否为非0, 若为空字符串, 则为false
注: -n可省略
== 判断str1和str2是否相等, 若相等, 则回传true
!= 判断str1和str2是否不相等, 若相等, 则回传false

0.6 多重条件

test -r filename -o -w filename 或 [ -r "filename"  -o  -w "filename" ] 或 [ -r "filename" ] -o [ -w "filename" ]
测试标志 代表意义
-a
-o
!

1. 条件判断

1.1 if...then...

if [ condition ]; then
    程序段
elif [ condition ]; then
    程序段
else
    程序段
if

1.2 case...esac

只针对某几种特殊情况进行设置.
系统很多服务的启动script都是用这种写法的.

case ${变量名称} in 
    "第一个变量内容")  #每个变量内容双引号括起来, 关键字则为小括号
        程序段
    ;;              #每个类型结尾使用两个连续的分号来处理
    "第二个变量内容")
        程序段
    ;;
    *)              #最后一个变量内容都会用*来代表其他所有值
        程序段
        exit 1      #此处千万不要忘记!
    ;;
esac

case支持glob风格的通配符:

  • * : 任意长度任意字符
  • ? : 任意单个字符
  • [ ] : 指定范围内的任意单个字符
  • a|b : a或b

2. 函数

实现功能, 减少重复.
注意shell script的执行方式从上到下, 从左到右, 因此shell script中function的设置一定要写在最前面.
function也是有内置变量的.

# 语法一:
function fname() {
    ...函数体...           #函数的内置变量在函数定义的代码块中有$, 在程序块中引用函数时, 无$
}
# 语法二:
f_name () {
    ...函数体...
}

调用: 函数只有被调用才会执行
调用: 给定函数名 (函数名出现的地方, 会被自动替换为函数代码)
函数的生命周期: 被调用时创建, 返回时终止
return命令返回自定义的状态结果:
0: 成功
1 - 255: 失败

函数可以接受参数:
传递参数给函数: 调用函数时, 在函数名后面以空白分隔参数列表即可, 例如: testfunc arg1 arg2
在函数体中, 可使用$1, $2, ...调用这些参数, 还可使用$@, $*, $#等特殊变量

变量作用域:
本地变量: 当前shell进程(当前shell脚本程序文件)
局部变量: 函数的生命周期, 函数结束时被自动销毁
如果函数中有变量与本地变量名称相同, 若不用local声明该变量为局部变量, 则在函数操作时会修改本地变量的值

​ 在函数中定义局部变量的方法:
local NAME=VALUE

函数递归:
函数直接或间接调用自身:
n!=n(n-1)(n-2)...1
斐波那契数组: 1 1 2 3 5 8 13 ...

foo () {
    if [ $1 = 0 -o $1 = 1 ]; then
        echo 1
    else
        echo $[$1*$(foo $[$1-1])]
    fi
}
foo 6

febo () {
    if [ $1 = 1 -o $1 = 2 ]; then
        echo 1
    else
        echo $[$(febo $[$1-1])+$(febo [$1-2])]
    fi
}
febo 10

3. 循环

3.1 不定循环

3.1.1 while do done

当条件成立, 执行循环, 否则停止.

while [ condition ]
do                  # do是循环的开始
    程序段
done                # done是循环的结束

3.1.2 until do done

直到条件成立, 终止循环, 否则循环执行程序段.

until [ condition ]
do                  # do是循环的开始
    程序段
done                # done是循环的结束

3.2 固定循环

3.2.1 for do done

for var in con1 con2 con3 ...   # 注: 用空格隔开, 中间不需要加逗号!!!
do
    程序段
done

3.2.2 for do done的数值处理

for (( 初始值; 限制值; 执行步长 ))
do
    程序段
done

# 实例
# 计算1加到100的值
sum=0
for ((i=1; i<=100; i=i+1))
do
    sum=$(( sum+i ))        # shell脚本中计算时要用$(( ))
done

4. shell script的追踪与调试

# 用法
sh [-nvx] script.sh
#   -n  不执行脚本, 仅查询语法问题
#   -v  在执行脚本前, 先将script的内容输出到屏幕上
#   -x  将命令的执行过程显示在屏幕上, 如此用户便可以判断程序代码执行到哪一段出了问题, 很有用!

你可能感兴趣的:(shell script编程)