Shell 脚本编程

RUNOOB.COM -- Shell 脚本编程

  1. Shell 教程 
  2. Shell 变量  
  3. Shell 传递参数 
  4. Shell 数组 
  5. Shell 运算符 
  6. Shell echo命令  
  7. Shell printf 命令 
  8. Shell test 命令 
  9. Shell 流程控制 
  10. Shell 函数 
  11. Shell 输入/输出重定向 
  12. Shell 文件包含 
#!/bin/bash
echo "Hello World !"

#!告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

另外,还有几个特殊字符用来处理参数:

参数处理说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。
   如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
   $@与$*相同,但是使用时加引号,并在引号中返回每个参数。
   如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

$* 与 $@ 区别:

  • 相同点:都是引用所有参数。
  • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):

#!/bin/bash

val=`expr 2 + 2`
echo "两数之和为 : $val"

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

算数运算符 +  -  *  /  %  =  ==  !=  

注意:

  • 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
  • 在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 "*" 不需要转义符号 "\" 

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。
-ne检测两个数是否不相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大于等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。


下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
!非运算,表达式为 true 则返回 false,否则返回 true。
[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。
[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。
[ $a -lt 20 -a $b -gt 100 ] 返回 false。


以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
&&逻辑的 AND[[ $a -lt 100 && $b -gt 100 ]] 返回 false
||逻辑的 OR[[ $a -lt 100 || $b -gt 100 ]] 返回 true


下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。-n检测字符串长度是否为0,不为0返回 true。[ -n "$a" ] 返回 true。str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。


文件测试运算符用于检测 Unix 文件的各种属性。
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是有名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。


echo "It is a test" 输出字符串,这里的双引号完全可以省略。
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
echo -e "OK! \n" # -e 开启转义
echo -e "OK! \c" # -e 开启转义 \c 不换行
原样输出字符串,不进行转义或取变量(用单引号)


显示命令执行结果 echo `date`
输出 Thu Jul 24 10:08:46 CST 2014 

注意: 这里使用的是反引号 `, 而不是单引号 '

printf 命令的语法:

printf  format-string[arguments...]

参数说明:

  • format-string: 为格式控制字符串
  • arguments: 为参数列表。
printf "%-10s %-8s %-4s\n"姓名性别体重kg  
printf "%-10s %-8s %-4.2f\n"郭靖66.1234 
printf "%-10s %-8s %-4.2f\n"杨过48.6543 
printf "%-10s %-8s %-4.2f\n"郭芙47.9876 

姓名     性别   体重kg
郭靖     男      66.12
杨过     男      48.65
郭芙     女      47.99
%s %c %d %f都是格式替代符
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中.2指保留2位小数。
\a警告字符,通常为ASCII的BEL字符
\b后退
\c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f换页(formfeed)
\n换行
\r回车(Carriage return)
\t水平制表符
\v垂直制表符
\\一个字面上的反斜杠字符
\ddd表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd表示1到3位的八进制值字符

$ printf "a string, no processing:<%b>\n" "A\nB"
a string, no processing:

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

if test $[num1]-eq $[num2]then
    echo '两个数相等!'else
    echo '两个数不相等!'fi

代码中的 [] 执行基本的算数运算

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

在sh/bash里可不能这么写,如果else分支没有语句执行,就不要写这个else。

forvarin item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。

in列表是可选的,如果不用它,for循环使用命令行的位置参数。

while condition
do
    command
done


#!/bin/bashint=1while(( $int<=5))do
    echo $int
    let"int++"done

使用中使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量,具体可查阅:Bash let 命令

while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量FILM,按结束循环。

echo '按下  退出'
echo -n '输入你最喜欢的网站名: 'while read FILM
do
    echo "是的!$FILM 是一个好网站"done


until condition
do
    command
done


casein模式1)
    command1
    command2
    ...
    commandN
    ;;模式2
    command1
    command2
    ...
    commandN
    ;;esac

case工作方式如上所示。取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。

break命令允许跳出所有循环(终止执行后面的所有循环)。
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

case的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。shell中函数的定义格式如下:

[ function ] funname [()]

{

    action;

    [return int;]

}

说明:

  • 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)