shell编程实战——Learn|shell编程实战——Learn By Example


shell编程实战——Learn By Example 2010-11-16 星期二 清冷 一直都是在命令行上使用shell命令,但是却没有写过shell脚本,今天刚好要将国际站的所有代码拉到本地grep看修改点。人肉肯定是不行的,分支实在太多了,写个shell脚本吧^_^ svncotrunk.sh

#!/bin/bash### 从svn上将指定的SVN URL递归将所有应用的trunk(有时间改成支持pattern)分支co到本地目录 ### # 例如: svnco http://svn.alibaba-inc.com/repos/ali_intl/apps/intl-biz/escrow/ destdir(目标根目录,默认是当前目录) # #输入:svnurl #操作:将给定URL的所有应用拉到本地某个目录(默认是当前目录) #算法: # 如果svnurl包含trunk,则直接svn co svnurl substr(svnurl)/trunk # 否则如果svnurl包含branch/tags,则直接忽略(因为branch/tags分支太多了,需要额外信息明确要co的分支) # 否则,说明这是在上层目录中,对svnurl的每个子目录,递归做上面的操作(递归终止条件:svnurl含有branch/tags/trunk 或者 > maxdepth=5)## Shell脚本中的函数必须先定义后调用,一般把函数定义都写在脚本的前面,把函数调用和其它命令写在脚本的最后 ## 参数:当一个函数被调用时,脚本程序的位置参数$*、$@、$#、$1, $2, ..等会被替换成函数的参数。这个跟shell的命令行参数是一样的处理方式。当函数执行完毕,这些参数会恢复它们先前的值。 ## 局部变量:可以使用local关键字在shell函数中声明局部变量,局部变量将局限在函数的作用范围内。 ## 返回值:如果在函数里没有使用return命令指定一个返回值,函数返回的就是执行的最后一条命令的退出码; 如果return后面跟一个数字则表示函数的Exit Status。shell的函数返回值只能是整数,作为函数的退出状态,and this exit status is assigned to the variable $?.## 检查给字符串是不是以某个子字符串结尾 end_with() { local src=https://www.it610.com/article/$1 local pattern=$2ret=`echo $src | grep $pattern$`if [ -z"$ret" ] #not found then return 1 else return 0 fi }## 检查给定字符串是不是包含指定子字符串 # 这里用来判断是否包含/trunk/tags/branches contains() { local src=https://www.it610.com/article/$1 local pattern=$2 ret=`echo $src | grep $pattern` if [ -z"$ret" ] #not found then return 1 else return 0 fi }## 从svnurl中获取保存本地的目录名 ## 如:http://svn.alibaba-inc.com/repos/ali_intl/apps/intl-biz/escrow/trunk/ ==> ali_intl/apps/intl-biz/escrow/ ##http://svn.alibaba-inc.com/repos/ali_intl/apps/intl-biz/escrow/trade/trunk/biztrade/ ==> ali_intl/apps/intl-biz/escrow/trade/biztrade/ get_path_from_svnurl() { local svnurl=$1 echo $svnurl | sed 's#http://svn.alibaba-inc.com/repos/##' | sed 's#trunk/##' }get_svncourl_from_svnurl() { local svncourl=$1 svncourl=${svncourl%%trunk*} local TRUNK="trunk/" echo $svncourl$TRUNK }### 从svn上将指定的SVN URL递归将所有应用的trunk(有时间改成支持pattern)分支co到本地目录 ### # 例如: svnco http://svn.alibaba-inc.com/repos/ali_intl/apps/intl-biz/escrow/ destdir(目标根目录,默认是当前目录) function svncotrunk(){ #为了方便后面的判断和子svnurl拼接 if end_with $1 "/"; then local svnurl="$1" else local svnurl="$1/" fi local depth=$2 # 超过递归最大层次,退出 if [ $depth -lt 0 ]; then datetime=`date +"%y-%m-%d %H:%M:%S"` echo "$datetime ERROR: Recursive depth exceed $MAX_DEPTH for $svnurl" echo "$datetime ERROR: Recursive depth exceed $MAX_DEPTH for $svnurl" >> $SVN_CO_LOG return 1 fi# 注意Shell中的函数调用不写括号,否则会报错;参数之间是用空格隔开,而不是逗号 # Remember that the exit status of zero is a true condition in shell programming. if contains $svnurl "/archived/"; then echo "Ignore archived url" elif contains $svnurl "/trunk/"; then # 从svnurl中截取以trunk/结尾的那部分url local svncourl=`get_svncourl_from_svnurl $svnurl` # 保存分支到一个统计文件 datetime=`date +"%y-%m-%d %H:%M:%S"` echo "$datetime==>$svncourl" >> $SVN_CO_LOG local path=`get_path_from_svnurl $svncourl` svn co $svncourl $path elif contains $svnurl "/branches/" || contains $svnurl "/tags/" || contains $svnurl "/milestone/"; then echo "This is a branch or tag or milestone, we don't deal with braches or tags or milestone right now!" else subdirs=`svn ls $svnurl` for subdir in $subdirs; do subsvnurl=$svnurl$subdir # Recursive svncotrunk $subsvnurl `expr $depth - 1`#注意减号两旁必须有空格,否则会被当作字符串拼接 done fi }MAX_DEPTH=8# we have less than 1 argument. Print the help text: if [ $# -lt 1 ]; then cat<< HELPNAME svncotrunk -- 从svn上将指定的SVN URL递归将所有子分支的trunk分支co到本地目录 SYNOPSTS svncotrunk svnurl [svnco.log path] [depth=8] DESCRIPTION 从svn上将指定的SVN URL递归将所有子分支的trunk分支co到本地目录, 将svn co分支保存在svnco.log文件中(如果没有指定文件,默认是当前目录下的svnco.log)例如: svncotrunk http://svn.alibaba-inc.com/repos/ali_intl/apps/intl-biz/escrow/ cohistory.logHELP exit 0 elif [ $# -eq 1 ]; then SVN_CO_LOG="svnco.log" svncotrunk $1 MAX_DEPTH elif [ $# -eq 2 ]; then SVN_CO_LOG=$2 svncotrunk $1 $MAX_DEPTH elif [ $# -ge 3 ]; then MAX_DEPTH=$3 svncotrunk $1 $MAX_DEPTH fi

【shell编程实战——Learn|shell编程实战——Learn By Example】
关于函数和返回值 法一: 使用 return 这个命令,把函数中某个数值返回,其实是使用Exist Status作为返回值,使用$?接收返回值 法二: 在函数中使用 echo 输出想要返回的结果,使用`function call`接收函数输出结果。 Output can be in the form of stdout or a return code value or both.
这两者往往是结合在一起的,如果你不想显示在stdout中显示函数的echo值,可以采用function > /dev/null将函数的echo输出到黑洞中。
参考资料: 1. Shell 编程中的函数返回值http://hi.baidu.com/jidongxx/blog/item/03d06bf07e8049a2a50f5237.html 2. Functionshttp://www.injunea.demon.co.uk/pages/page212.htm 3. 13. Functionshttp://steve-parker.org/sh/functions.shtml 4. Chapter 6. Exit and Exit Statushttp://www.faqs.org/docs/abs/HTML/exit-status.html

    推荐阅读