读书人

Shell编程基础 part 二/2

发布时间: 2013-11-08 17:52:14 作者: rapoo

Shell编程基础 part 2/2

6 命令行参数

特殊变量$*, $1, $2, ...$9包含了用户从命令行输入的参数; 简单的命令行语法(强制性参数和查看帮助的-h选项); 在编写复杂程序时, 可能需要更多的自定义选项; 通常的惯例是在所有可选的参数之前添上一个减号 - , 后面跟参数值(文件名);

e.g. 实现对输入参数的分析: case

123456789101112131415161718192021222324help(){ cat << HELP This is a generic command line parser demo. USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2HELP exit 0} while [ -n "$1" ]; docase "$1" in -h) help;shift 1;; # function help is called -f) opt_f=1;shift 1;; # variable opt_f is set -l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2 --) shift;break;; # end of options -*) echo "error: no such option $1. -h for help";exit 1;; *) break;;esacdone echo "opt_f is $opt_f"echo "opt_l is $opt_l"echo "first arg is $1"echo "2nd arg is $2"

>运行脚本: cmdparser -l hello -f -- -somefile1 somefile2;

>输出: opt_f is 1; opt_l is hello; first arg is -somefile1; 2nd arg is somefile2;

>脚本首先在所有输入命令行参数中进行循环, 将输入参数与case表达式进行比较, 如果匹配则配置一个变量并且移除该参数; 根据unix惯例, 首先输入的应该是包含减号的参数;


7 Shell脚本示例

一般编程步骤

任何优秀的脚本都应该有帮助和输入参数; 写一个框架脚本framework.sh, 包含大多数脚本需要的框架结构是一个好主意;

这样, 在开始编写新脚本时, 可以先执行以下命令: cp framework.sh myscript ; 然后再插入自己的函数; [节省时间, 规范代码]


二进制到十进制的转换

脚本b2d将二进制数转换为相应的十进制, 利用expr命令进行数学运算;

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#!/bin/bash# vim: set sw=4 ts=4 et:help(){ cat << HELP b2d -- convert binary to decimal USAGE: b2d [-h] binarynum OPTIONS: -h help text EXAMPLE: b2d 111010will return 58HELP exit 0} error(){ # print an error and exit echo "$1" exit 1} lastchar(){ # return the last character of a string in $rval if [ -z "$1" ]; then # empty string rval="" return fi # wc puts some space behind the output this is why we need sed: numofchar=`echo -n "$1" | sed 's/ //g' | wc -c ` # now cut out the last char rval=`echo -n "$1" | cut -b $numofchar`} chop(){ # remove the last character in string and return it in $rval if [ -z "$1" ]; then # empty string rval="" return fi # wc puts some space behind the output this is why we need sed: numofchar=`echo -n "$1" | wc -c | sed 's/ //g' ` if [ "$numofchar" = "1" ]; then # only one char in string rval="" return fi numofcharminus1=`expr $numofchar "-" 1` # now cut all but the last char: rval=`echo -n "$1" | cut -b -$numofcharminus1` #原来的 rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`运行时出错. #原因是cut从1开始计数,应该是cut -b 1-${numofcharminus1}} while [ -n "$1" ]; docase $1 in -h) help;shift 1;; # function help is called --) shift;break;; # end of options -*) error "error: no such option $1. -h for help";; *) break;;esacdone # The main programsum=0weight=1# one arg must be given:[ -z "$1" ] && helpbinnum="$1"binnumorig="$1" while [ -n "$binnum" ]; do lastchar "$binnum" if [ "$rval" = "1" ]; then sum=`expr "$weight" "+" "$sum"` fi # remove the last position in $binnum chop "$binnum" binnum="$rval" weight=`expr "$weight" "*" 2`done echo "binary $binnumorig is decimal $sum"#

>使用的算法是十进制和二进制数权值(1 2 4 8 16...), e.g. 二进制10 -> 0 * 1 + 1 * 2 = 2;

>lastchar函数得到单个的二进制数, 该函数使用wc -c计算字符个数, 然后用cut命令取出末尾一个字符; chop函数的功能是移除最后一个字符;


文件循环拷贝

e.g. 将所有发出的邮件保存到一个文件中; 过了一段时间后这个文件可能会变很大以至于文件访问速度变慢; 脚本rotatefile可以重命名邮件保存文件为outmail.1, 把原来的outmail.1变成outmail.2等等...

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162#!/bin/bash# vim: set sw=4 ts=4 et: ver="0.1"help(){ cat << HELP rotatefile -- rotate the file name USAGE: rotatefile [-h] filename OPTIONS: -h help text EXAMPLE: rotatefile out This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1[BR] and create an empty out-file The max number is 10 version $ver HELP exit 0} error(){ echo "$1" exit 1} while [ -n "$1" ]; do case $1 in -h) help;shift 1;; --) break;; -*) echo "error: no such option $1. -h for help";exit 1;; *) break;; esacdone # input check:if [ -z "$1" ] ; then error "ERROR: you must specify a file, use -h for help"fi filen="$1"# rename any .1 , .2 etc file:for n in 9 8 7 6 5 4 3 2 1; do if [ -f "$filen.$n" ]; then p=`expr $n + 1` echo "mv $filen.$n $filen.$p" mv $filen.$n $filen.$p fidone # rename the original file:if [ -f "$filen" ]; then echo "mv $filen $filen.1" mv $filen $filen.1fi echo touch $filentouch $filen

>检测到用户提供了一个文件名之后, 先进行一个9到1的循环, 文件名.9 重命名为 文件名.10, .8 -> .9 ... 循环结束后把原始文件命名为 文件名.1 ,同时创建一个和原始文件同名的空文件(touch $filen);


脚本调试

最简单的调试方法是使用echo命令; [print流派...] 可以在任何怀疑会出错的地方用echo打印变量值, 大部分shell程序员花费80%时间用于调试; shell脚本的好处在于无需重新编译, 插入echo命令也不需要多少时间;

shell也有调试模式, 如果脚本strangescript出错, 可以使用:

1sh -x strangescript

>执行脚本, 同时显示所有变量的值; [每一步输出]

shell还有不执行脚本只检查语法的模式:

1sh -n your_script

>这个命令会返回所有语法错误;

---The End---

refer to http://wiki.ubuntu.com.cn/Shell%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80

读书人网 >编程

热点推荐