Shell编程基础 part 2/2

27 篇文章 0 订阅
6 篇文章 0 订阅

6 命令行参数

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
help()
{
    cat  << HELP
    This is a generic  command  line parser demo.
    USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2
HELP
    exit  0
}
 
while  [ -n  "$1"  ];  do
case  "$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 ;;
esac
done
 
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命令进行数学运算;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/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 111010
will  return  58
HELP
    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"  ];  do
case  $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 ;;
esac
done
 
# The main program
sum =0
weight=1
# one arg must be given:
[ -z  "$1"  ] && help
binnum= "$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等等...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/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 ;;
    esac
done
 
# 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  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
    fi
done
 
# rename the original file:
if  [ -f  "$filen"  ];  then
    echo  "mv $filen $filen.1"
    mv  $filen $filen.1
fi
 
echo  touch  $filen
touch  $filen

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


脚本调试

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

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

1
sh -x strangescript

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

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

1
sh -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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值