<!-- toc -->

<!-- tocstop -->


shell脚本编程的特点

简单、快速以及轻松

第一个shell脚本编程

为了能成功编写有一个shell脚本,需要做三件事情

  1. 写一个脚本
  2. 赋予脚本可执行权限
  3. 把脚本放在shell可以找到的某个地方

如下是一个文件,文件名hello_world

1
2
3
4
#!/bin/sh
# 第一行#!是声明指令,来调用这个脚本的shell来检测
# My first script
echo "hello world!"

1. 编程的基本要素

1.1 变量

变量是通过名字能访问到的存储信息的内存。

与大多数解释型语言相同,shell编程中变量无需事先声明。shell对变量是一视同仁的,只要看到以 $ 开始的单词,它就去寻找变量的值然后替换它。

变量名的命名必须遵循以下规则:

  • 首个字符必须为字母(a-z,A-Z
  • 中间不能有空格,可以使用下划线(_
  • 不能使用标点符号
  • 不能使用bash里的关键字(可用help命令查看保留关键字)

1.2 运算

只提供了整数的数学运算,并且不检测溢出。和其他语言一样,对除法运算的要求是除数不能为0,也可以捕获到除以零的情况并报错。

1
2
3
weight=1
weight=$weight+1
echo $weight

打印出来的结果不是2而是1+1。为了达到我们的预期效果,有以下集中表达方式可供参考(基本的运算除了有加减乘除+-*/,还有取余运算):

  • expr用于整数值运算,每一项用空格隔开
    1
    2
    > weight=`expr $weight + 1`
    >

注意“+”号两边的空格,否则还是按照字符串的方式赋值。“`”符号与$(命令)的语法等效,用于获取命令的stdout中的内容。expr实际上是一个命令,表达式计算结果输出到stdout中。做乘法时需要注意,因为“*”在shell中有特殊意义,所以应该写成“\*”或者用引号“"*"”括起来。另外,`命令`是一种古老的表示方法,用$(命令)更好。

  • let 表示数学运算 let "weight+=1"let "weight=$weight+1"
  • (())方式与let类型 ((weight+=1))((weight=$weight+1))
  • $[]将中括号内的表达式作为数学运算先计算结果再输出 weight=$[$weight+1]

1.3 流程控制

脚本程序包含了一系列的命令,一行一行地开始执行直到最后结束。但是大多数程序的结构不止如此,还有比较复杂的逻辑,会根据不同情况(条件)进行不同的动作。通过使用shell提供的 if 、 exit 、 for 、 while 、 until 、 case 、 break 、 continue 这些关键字我们可以控制执行的顺序。

1. if 语句

if 命令有三种形式

  • 第一种
    1
    2
    3
    4
    5
    > #条件为真执行;条件为假不做任何事情
    > if condition ; then
    > commands
    > fi
    >
  • 第二种
    1
    2
    3
    4
    5
    6
    7
    > #条件为真执行command1;条件为假执行command2
    > if condition ; then
    > command1
    > else
    > command2
    > fi
    >
  • 第三种
    1
    2
    3
    4
    5
    6
    7
    > #条件1为真执行command1;条件2为真时执行command2
    > if condition1 ; then
    > command1
    > elif condition2 ; then
    > command2
    > fi
    >
2. test 语句

一个正确编写的Unix应用程序会告诉操作系统执行地成功与否。它用什么方法告诉系统呢?那就是我们经常用到的exit状态。exit的状态数值的范围为0~255。“0”表示成功,其他数值都表示失败。exit状态有两个很重要的功能。第一个作用是检测和处理错误,第二个作用是可以执行 true/false 测试。 这种 true/false 的判断经常时通过test和if一起配合实现的,可以有两种语法形式:

  • 第一种形式
    test expression
  • 第二种形式 (注意:“[”、“]”和expression 之间必须有空格)
    [ expression ]

test 命令工作很简单。如果给定的表达式为true,test退出的状态值为0,否则退出的状态值为1。
test 命令可以判断3类条件:

  1. 数值比较
  • -eq [ n1 -eq n2 ] 检查n1是否与n2相等
  • -ge [ n1 -ge n2 ] 检查n1是否大于或等于n2
  • -gt [ n1 -gt n2 ] 检查n1是否大于n2
  • -le [ n1 -le n2 ] 检查n1是否小于或等于n2
  • -lt [ n1 -lt n2 ] 检查n1是否小于n2
  • -ne [ n1 -ne n2 ] 检查n1是否不等于n2
  1. 字符串比较
  • = [ str1 = str2 ] 检查str1是否和str2相同
  • != [ str1 != str2 ] 检查str1是否和str2不同
  • < [ str1 < str2 ] 检查str1是否比str2小
  • > [ str1 > str2 ] 检查str1是否比str2大
  • -n [ -n str1 ] 检查str1的长度是否非0
  • -z [ -z str1 ] 检查str1的长度是否为0
  1. 文件比较
  • -d [ -d file ] 检查file是否存在并且是一个目录
  • -e [ -e file ] 检查file是否存在
  • -f [ -f file ] 检查file是否存在并且是一个文件
  • -r [ -r file ] 检查file是否存在并且可读
  • -s [ -s file ] 检查file是否存在并且非空
  • -w [ -w file ] 检查file是否存在并且可写
  • -x [ -x file ] 检查file是否存在并且可执行
  • -O [ -O file ] 检查file是否存在并且属当前用户所有
  • -G [ -G file ] 检查file是否存在并且默认组与当前用户相同
  • -nt [ file1 -nt file2 ] 检查file1是否比file2新
  • -ot [ file1 -ot file2 ] 检查file1是否比file2旧
3. exit 语句

一个好的脚本编程者应该在脚本完成时设置 exit 状态。为了实现这个要求,就要使用 exit 命令。exit命令使脚本带着状态值立刻退出。例如:

1
2
exit 0 # 退出脚本,状态值为0 (成功)
exit 1 # 退出脚本,状态值为1 (失败)

4. case 语句

case表达式可以用来匹配一个给定的字符串,而不是数字。case语句有以下格式:

1
2
3
case word in
模式) 声明 ;;
esac

1
2
3
4
5
6
case $1 in
-h) help; shift 1;; #调用help函数
--) shift; break;; #结束选项
-*) error "error: no such option $1. -h for help";; # 错误提示
*) break;; #退出判断
esac

上面使用了一个特殊变量$1,该变量包含有传递给这个脚本的第一个参数值。“*”意味着匹配任何东西。在最后的模式匹配中加入*这项是个好习惯,可以用它来检测非法的输入。

5. for/while 循环语句

循环是只要条件成立就反复执行。shell有两种形式的循环,一种是while(until),另一种是for。

1
2
3
while ... ; do
...
done

只要测试表达式条件为真,则while循环将一直运行。关键字“break”用来跳出循环,而关键字“continue”则可以跳过一个循环的余下部分,直接跳到下一次循环中。 for循环会查看一个字符串行表(字符串用空格分隔),若找到匹配进行循环:

1
2
3
for var in ... ; do
...
done