首页 > 其他 > 详细

shell programming tutorial

时间:2014-02-20 03:13:59      阅读:390      评论:0      收藏:0      [点我收藏+]

一、什么是shell程序

以文件形式存放批量的Linux命令集合,该文件能够被Shell解释执行,这种文件就是Shell脚本程序

通常由一段Linux命令、Shell命令、控制语句以及注释语句构成

Shell 脚本的编写

Shell 脚本是纯文本文件,可以使用任何文本编辑器编写

Shell 脚本通常是以 .sh 作为后缀名

第一行:指定用哪个程序来编译和执行脚本。#!/bin/bash

注释行:使用(#)符号


二、shell编程的主要内容

变量

本地变量、环境变量、位置参量

输入输出

read/echo或printf

条件测试

整数测试、逻辑测试、字符串测试

控制语句

条件/循环/分支/

函数
常用Shell程序内置指令

declare/export/eval/trap等


三、变量

(一)变量概述


bubuko.com,布布扣


(二)变量常见操作

bubuko.com,布布扣


(三)环境变量和只读变量

bubuko.com,布布扣


(四)位置参量(命令行参数)

 位置参量是一组特殊的内置变量,通常被 shell 脚本用来从命令行接受参数,或被函数用来保存传递给它的参数。

 执行 shell 脚本时,用户可以通过命令行向脚本传递信息,跟在脚本名后面的用空格隔开的每个字符串都称为位置参量。

在脚本中使用这些参数时,需通过位置参量来引用。例如: $1 表示第一个参数,$2 表示第二个参数,以此类推。 $9 以后需要用花

括号把数字括起来,如第 10 个位置参量以  ${10} 的方式来访问。

bubuko.com,布布扣

#例1:shell_test.sh 
echo “the count of parameters:$#”
echo “first param=$1”
echo “second param=$2”
echo “params’ string=$*”

shell_test.sh This is Peter

shell_test.sh This is "Peter Piper"    //如果位置参量中含有空格,则需要使用双引号


(五)数组

bubuko.com,布布扣


四、输入输出

(一)输入--read命令

read var

从标准输入读取一行并赋值给变量var

read

标准输入读取一行并赋值给内置变量REPLY

read -a arr

读入一组词,依次赋值给数组arr


read -p "please input 5 digits:" -t 10 -a arr3  // -p 提示符 -t 超时

stty -echo // 输入不回显    

stty echo // 输入回显


(二)输出--echo 命令

echo $num 或 echo ${num}   //输出一行文本

echo -n “Hello World”  // -n 去掉换行符
echo -e “\t” “Hello World”   // -e 支持转义


(三)echo输出颜色与光标定位:

\33[30m -- \33[37m   设置前景色(字体颜色)
\33[40m -- \33[47m   设置背景色
\33[y;xH设置光标位置

bubuko.com,布布扣

echo –e “\033[31mthis is a test”
echo -e "\033[10;5H\033[31;46mthis is a test“
echo -e "\033[0m" // 取消全部设置


五、算术扩展

(一)单引号、双引号、反引号区别

单引号 忽略所有特殊字符
双引号 忽略大部分特殊字符($,`等字符除外) 参考这里 或者尝试  X=*;   echo $X;   echo ‘$X‘;  echo "$X"; 的区别
反引号 命令替换(将一个命令的标准输出插入到命令的任何位置
$()     同上
命令替换可以嵌套
 如果使用反引号,则内部的反引号必须用反斜杠来转义。

echo  `basename \`pwd\``

echo  $(basename  $(pwd))


算术运算符:

+-*/(四则运算)

**%      (幂运算 和 模运算,取余数)

<<>>     (按位左移 和 按位右移)

&^|   (按位 、按位异或 和 按位

=+=-=*=/=%= 
<<= >>=&=^=|=   (赋值运算)

<><=>===!=    (比较操作符)

&&||    (逻辑 和 逻辑


算术扩展:

$[] n=5;  echo $[$n+1]
$(()) n=5;  echo $(($n+1))
(()) ((n+=1));  echo $n
expr
expr 4 + 5 注意+号两边要有空格
     r=`expr 4 + 5`
r=`expr 4 \* 5`
let   // 内置命令  type let
   let n=n+1
   let “n = n + 1”
   let “n=n+abc”    // abc 当做0


六、条件测试

任何一种测试中,都要有退出状态(返回值),退出状态为 0 表示命令成功或表达式为真,非0 则表示命令失败或表达式为假。

状态变量 $? 中保存命令退出状态的值

grep  study /etc/passwd; echo$?

grep   hello  /etc/passwd;echo$?


(一)测试表达式的值

表达式测试包括字符串测试、整数测试和文件测试。

通常用 test 命令来测试表达式的值

x=5; y=10
test $x -gt $y
echo $?

test 命令可以用 方括号 来代替(方括号前后要留空格)

x=5; y=10
[ $x -gt $y ] 
echo $?

2.x 版本以上的 Bash 中可以用双方括号来测试表达式的值,此时可以使用通配符进行模式匹配。

name=Tom

[[ $name = [Tt]?? ]] 
echo $?


(二)字符串测试(方括号只能使用!=  ==) //字符串测试最好加上"  "

[ -z$str]

如果字符串 str 长度为0,返回真

[ -n$str]

如果字符串 str 长度不为0,返回真

[ $str1=$str2]

两字符串相等

[ $str1!=$str2]

两字符串不等


name=Tom; [ -z $name ]; echo $?

name2=Andy; [ $name == $name2 ] ; echo $?


(三)整数测试 //操作符两边必须留空格!

[ int1-eqint2]

 int1等于int2

[ int1-neint2]

 int1不等于int2

[ int1-gtint2]

 int1大于int2

[ int1-geint2]

 int1大于或等于int2

[ int1-ltint2]

 int1小于int2

[ int1-leint2]

 int1小于或等于int2


x=1; [ $x -eq 1 ]; echo $?

整数测试也可以使用 let 命令或双圆括号:

相应的操作符为:== 、!= 、> 、>= 、< 、<=

x=1; let "$x == 1"; echo $?

x=1; (($x+1>= 2 )); echo $? 


let 和 双圆括号中可以使用算术表达式,而方括号不能
let 和 双圆括号中,操作符两边可以不留空格


(四)逻辑测试

[expr1-aexpr2]

逻辑,都为真时,结果为真

[expr1-oexpr2]

逻辑,有一个为真时,结果为真

[!expr]

逻辑


x=1; name=Tom;
[ $x -eq 1 –a –n $name ]; echo $?

[ ( $x -eq 1 ) –a ( –n $name ) ]; echo $?  //error, 不能随便添加括号


可以使用模式的逻辑测试:

[[pattern1&&pattern2]]

逻辑

[[pattern1||pattern2]]

逻辑

[[!pattern]]

逻辑

x=1; name=Tom;
[[ $x -eq 1 && $name = To? ]]; echo $?


(五)检查空值

[ "$name" = "" ]           [ ! "$name" ]                  [ "X${name}" = "X" ]


(六)文件测试

文件测试:文件是否存在,文件属性,访问权限等。更多文件测试符参见 man test

 -ffname

fname 存在且是普通文件时,返回真 ( 即返回0 )

 -L fname

fname 存在且是链接文件时,返回真

 -d fname

fname 存在且是一个目录时,返回真

 -e fname

fname(文件或目录)存在时,返回真

 -s fname

fname 存在且大小大于0 时,返回真

 -r fname

fname(文件或目录)存在且可读时,返回真

 -w fname

fname(文件或目录)存在且可写时,返回真

 -x fname

fname(文件或目录)存在且可执行时,返回真


(七)括号总结

${...}

获取变量值

$(...)

命令替换

$[...]

让无类型的变量参与算术运算

$((...))

同上

((…))

算术运算

[ ... ]

条件测试,等价于test命令

[[ ... ]]

条件测试,支持模式匹配与通配符


七、条件与分支语句

(一)if条件语句

if expr1      #如果expr1为真(返回值为0)

then          #那么

   commands1  #执行语句块commands1

elif  expr2    #expr1不真,而expr2为真

then          #那么

   commands2  #执行语句块commands2

 ... ...     #可以有多个elif语句

else          # else最多只能有一个

   commands4  #执行语句块commands4

fi            #if语句必须以单词fi终止


几点说明:

 elif 可以有任意多个(0 个或多个); else 最多只能有一个(0 个或 1 个); if 语句必须以 fi 表示结束

 expr 通常为条件测试表达式;也可以是多个命令,以最后一个命令的退出状态为条件值。

 commands 为可执行语句块,如果为空,需使用 shell 提供的空命令 “ : ”,即冒号。该命令不做任何事情,只返回一个退出状态 0

 if 语句可以嵌套使用。

(二)case 选择语句

case expr in # expr为表达式,关键词in不要忘!

  pattern1exprpattern1匹配,注意括号

   commands1 #  执行语句块commands1

   ;;        跳出case结构

  pattern2exprpattern2匹配

   commands2 #执行语句块commands2

   ;;        跳出case结构
 
......   可以有任意多个模式匹配

  *)        expr与上面的模式都不匹配

   commands  执行语句块commands

   ;;        跳出case结构
esac        case语句必须以esac终止


几点说明:

 表达式 expr 按顺序匹配每个模式,一旦有一个模式匹配成功,则执行该模式后面的所有命令,然后退出 case。

 如果 expr 没有找到匹配的模式,则执行缺省值 “ *) ” 后面的命令块 ( 类似于 if  中的 else ); “ *) ” 可以不出现。

 所给的匹配模式 pattern 中可以含有通配符和“ | ”。

 每个命令块的最后必须有一个双分号,可以独占一行,或放在最后一个命令的后面。


八、循环语句

(一)for 循环

for variable  in  list

# 每一次循环,依次把列表list中的一个值赋给循环变量

do          #循环开始的标志

  commands  #循环变量每取一次值,循环体就执行一遍

done        #循环结束的标志

几点说明:

列表 list 可以是命令替换、变量名替换、字符串和文件名列表 ( 可包含通配符 )
 for 循环执行的次数取决于列表 list 中单词的个数
 for 循环体中一般要出现循环变量,但也可以不出现

可以省略  in list ,此时使用“$@”

for ((exp1;exp2;exp3)  //类似于C语言的for 循环
do
done


(二)while 和until循环

while expr  #执行expr

do #expr的退出状态为0,进入循环,否则退出while

  commands  #循环体

done        #循环结束标志,返回循环顶部


until expr  #执行expr

do #expr的退出状态非0,进入循环,否则退出until

  commands  #循环体

done        #循环结束标志,返回循环顶部


(三)break和continue、exit和sleep

break  [n]

用于强行退出当前循环。
 如果是嵌套循环,则 break 命令后面可以跟一数字 n,表示退出第 n 重循环(最里面的为第一重循环)。

continue [n]

 用于忽略本次循环的剩余部分,回到循环的顶部,继续下一次循环。
 如果是嵌套循环,continue 命令后面也可跟一数字 n,表示回到第 n 重循环的顶部。

exit n

exit 命令用于退出脚本或当前进程。n 是一个从 0 到 255 的整数,0 表示成功退出,非零表示遇到某种失败而非正常退出。该整数被保存在状态变量 $? 中。

sleep n  暂停 n 秒钟


(四)select循环和菜单

select variable in  list

do          #循环开始的标志

  commands  #循环变量每取一次值,循环体就执行一遍

done        #循环结束的标志

 select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示 PS3 提示符,等待用户输入
 用户输入菜单列表中的某个数字,执行相应的命令
 用户输入被保存在内置变量 REPLY 中。

 select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环。

 select 经常和 case 联合使用

 与 for 循环类似,可以省略 in list ,此时使用位置参量


九、函数

 一个函数就是一个子程序,用于完成特定的任务,当有重复代码,或者一个任务只需要很少的修改就被重复几次执行时, 这时你应考虑使用函数。

function function_name {

   commands

}

function_name() {

   commands

}

只需输入函数名即可调用该函数

 函数必须在调用之前定义

如果要调用其他文件的函数,可以在开头  . 文件名  //类似文件包含,也可以使用source

#!/bin/bash

fun2()

   echo "This is fun2."

   echo "Now exitingfun2."

}

fun2 #调用函数fun2


#! /bin/bash

func1()

{

        echo "theparameter‘s count:$#"

        echo "the firstparameter:$1"

        echo "the secondparameter:$2"

}

func1 a b


(一)字符串操作:

m 的取值从0 到${#var}-1

注:patternold中可以使用通配符

${#var}

返回字符串变量 var的长度

${var:m}

返回${var}中从m+1个字符到最后的部分

${var:m:len}

返回${var}中从m+1个字符开始,长度为len的部分

${var#pattern}

删除${var}开头部分与pattern匹配的最小部分

${var##pattern}

删除${var}开头部分与pattern匹配的最大部分

${var%pattern}

删除${var}结尾部分与pattern匹配的最小部分

${var%%pattern}

删除${var}结尾部分与pattern匹配的最大部分

${var/old/new}

new替换${var}中第一次出现的old

${var//old/new}

new替换${var}中所有的old(全局替换)


(二)随机数和 expr 命令

echo $RANDOM  // 生成随机数的特殊变量

expr通用的表达式计算命令
表达式中参数与操作符必须以空格分开,表达式中的运算可以是算术运算,比较运算,字符串运算和逻辑运算。

expr 5 % 3

expr 5 \* 3 #乘法符号必须被转义

注意:目前比较少使用,可用$[ ... ]替换


(三)shift 命令

一般用于函数或者脚本程序参数处理,特别是参数多于10以上的时候
将所有参数变量向下移动一个位置,$2变成$1,$3变成$2,依次递进,但$0保持不变

例如:

while [ "$1" != "" ]

do

    echo $1

    shift

done


(四)eval 命令

eval arg1 [arg2] ... [argN]

l将所有的参数连接成一个表达式,并计算或执行该表达式,参数中的任何变量都将被展开。

listpage="ls -l | more"

eval $listpage


(五)trap命令

trap command signal

command
一般情况下是Linux命令
’ ’表示发生陷阱时为空指令,不做任何动作
’-’表示发生陷阱时采用缺省指令
signal
HUP(1) 挂起;一般因终端掉线或用户退出而引发
INT(2) 中断;一般因按下”Ctrl+C”组合键引发
QUIT(3) 退出;一般因按下”Ctrl+\”组合键引发
ABRT(6) 异常中止;一般因某些严重的执行错误而引发
ALRM(14) 闹钟;一般是超时时钟到来而引发
TREM(15) 中止;一般由系统在关机的时候发出

#!/bin/bash

#安装23号信号

#处理代码为"rm-ftmp$$;exit0"

trap "rm -ftmp$$;exit 0" 2 3

#生成文件,文件名为tmp+当前进程号

touch tmp$$

#睡眠60秒,以便向当前进程发送信号

sleep 60


(六)declare 命令

declare或typeset内建命令(它们是完全相同的)可以用来限定变量的属性.这是在某些编程语言中使用的定义类型不严格的方式。命令declare是bash版本2之后才有的。命令typeset也可以在ksh脚本中运行。

-r 只读
   1 declare -r var1

(declare -r var1readonly var1作用相同)

这大致和C的const限定词相同.一个试图改变只读变量值的操作将会引起错误信息而失败.

-i 整数
    declare -i number
    # 脚本余下的部分会把"number"当作整数看待.	
-a 数组
    declare -a indices

变量indices会被当作数组.

-f 函数
    declare -f

在脚本中没有带任何参数的declare -f 会列出所有在此脚本前面已定义的函数出来。

    declare -f function_name

declare -f function_name则只会列出指定的函数.

-x export
    declare -x var3

这样将声明一个变量作为脚本的环境变量而被导出。

-x var=$value
    declare -x var3=373

declare命令允许在声明变量类型的时候同时给变量赋值。


(七)shell内置命令总结



echo

输出一行文本到标准输出设备

read

从标准输入设备读入数据

printf

格式化输出

declare

定义或创建变量或数组

let

让未定义的变量参与算术运算

expr

执行表达式

shift

把所有参数变量向下移动一个位置

eval

执行命令

trap

用来定义接收OS信号后而采取的动作

exit

退出SHELL程序

sleep

睡眠

test

条件测试


参考:

《鸟哥的Linux私房菜基础篇》

《高级bash shell编程指南》


shell programming tutorial

原文:http://blog.csdn.net/jnu_simba/article/details/19474327

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!