Shell Notes(3)
> 算术赋值 与 算术扩展
算术扩展:$((expression)) 用它给表达式赋值,并用得到的结果来取来$((expression))。用来显示表达式的值或把值赋给一个变量
算术赋值:let “expression” 或 ((expression)) 用来给表达式赋值,并返回一个状态码。用来进行逻辑比较或赋值运算
# 算术扩展可以看做是类似 int 型返回值的函数,而算术赋值是类似 void 型的,无返回值,但是有返回的状态信息
let “expression” 在一行内可以给多个变量赋值,表达式空格隔开
而((expression)) 用“,”将多个表达式隔开
eg. 1到100中3的倍数的数字之和:
$((expression))
let “expression”
((expression))
> 特殊符号
1) ` `
键盘tab上方,数字1左侧
我觉得就是个隔离容器,在` `中间执行一条shell指令,` `之外可以使用其返回结果
如前面的例子,seq 1 100,返回的是1到100的顺序序列,for var in `seq 1 100`,则是为var提供了一个遍历的空间,应该是先执行了seq 1 100,然后通过` `将结果返回,提供给for循环
2) [ ]
像if,while等都用到,我觉得是一个条件判断容器,[ ] 会将其中间内容条件判断结果返回。
如前面的例子,在$((expression))中,$(())本身值返回值,不返回状态,故需要借用[]进行条件判断
而let 和(())都是有状态返回的,故不再需要[]
> 逻辑表达式
_[[_expression_]]_ # _ 意为空格
与:&& 或:|| 大于:> 小于: < 等于:=
也可用 –gt –ge –lt –le –eq –ne
要说下的是字符串的比较,“=”支持模式匹配 [[ string=pattern ]],左侧是字符串,右侧是模式串
> 字符串模式匹配
${varname op pattern}
op可用的有
-------------------------------------------------
| # | 去除最小匹配前缀 |
| ## | 去除最大匹配前缀 |
| % | 去除最小匹配后缀 |
| %% | 去除最大匹配后缀 |
-------------------------------------------------
这些操作符一般用来操作路径名,以便提取或者移除某些组件,或者用来改变后缀。如下面的例子:
结果:
> 逻辑运算符
&& 和 ||
要说的是逻辑运算符的 lazy 特性。&& 和 || 都是二元,在计算时,如果仅通过左值就可以得到整个表达式的结果,就不再计算右值
如果 var1 || var2, 如果var1为true,则不再计算var2。想想,命令执行成功,则返回0,否则非零,此处,可借助&&的lazy特性,有条件地执行命令。
rm file1 || echo "delete file1 failed"
这里理解的时候有一个点要意识下:返回0,表示执行成功,成功为True,布尔运算,用的是True,不是返回值0;同理,返回值非零,表示不成功,为False。
实例:
1、写一个脚本makepath,给出一个路径名,然后根据路径名,依次创建多级目录,如:makepath a/b/c/d,依次创建出目录a,a/b,a/b/c,a/b/c/d
使用了局部变量path,避免了在递归过程成,共享变量造成意外。
2、一个多项选择考试的小程序。该程序从一个数据文件中读入问题,显示这些问题给用户,程序能辨别正确选项的编号和错误选项的编号。用户可以随时提交答案并计算得分,然后退出程序
1: #!/bin/bash
2: # a quiz program
3:
4: set -o xtrace
5:
6: #============================
7: function initialize ()
8: {
9: trap 'summarize ; exit 0' INT
10: num_ques=0
11: num_correct=0
12: first_time=true
13: cd ${QUIZDIR=./quiz} || exit 2
14: }
15:
16: #===========================
17: function choose_subj ()
18: {
19: subjects=($(ls))
20: PS3="Choose a subject for the quiz from the proceding list:"
21: select Subject in ${subjects[*]};do
22: if [[ -z "$Subject" ]];then
23: echo "No subject chosen. Bye." >&2
24: exit 1
25: fi
26: echo $Subject
27: return 0
28: done
29: }
30:
31: #===========================
32: function exchange ()
33: {
34: temp_value=${questions[$1]}
35: questions[$1]=${questions[$2]}
36: questions[$2]=$temp_value
37: }
38:
39: #===========================
40: function scramble ()
41: {
42: typeset -i index quescount
43: questions=($(ls))
44: questcount=${#questions[*]}
45: ((index=questcount-1))
46: while [[ $index -gt 0 ]];do
47: ((target=RANDOM%index))
48: exchange $target $index
49: ((index -= 1))
50: done
51: }
52:
53: #===========================
54: function ask ()
55: {
56: exec 3<$1
57: read -u3 ques || exit 2
58: read -u3 num_opts || exit 2
59:
60: index=0
61: choices=()
62: while (( index < num_opts )) ; do
63: read -u3 next_choice || exit 2
64: choices=("${choices[@]}" "$next_choice")
65: ((index+=1))
66: done
67: read -u3 correct_answer || exit 2
68: exec 3<&-
69:
70: if [[ $first_time = true ]];then
71: first_time=false
72: echo -e "You may process the interrupt key at any time to quit.\n"
73: fi
74:
75: PS3=$ques" "
76:
77: select answer in "${choices[@]}";do
78: if [[ -z "$answer" ]];then
79: echo "Not a valid choice. Please choose again"
80: elif [[ "$answer" = "$correct_answer" ]];then
81: echo "Correct!"
82: return 1
83: else
84: echo "No, the answer is $correct_answer."
85: return 0
86: fi
87: done
88: }
89:
90: #================================
91: function summarize ()
92: {
93: echo
94: if (( num_ques == 0));then
95: echo "You did not answer any questions"
96: exit 0
97: fi
98:
99: (( percent=num_correct*100/num_ques ))
100: echo "You answered $num_correct questions correctly, out of \
101: $num_ques total questions."
102: echo "Your score is $percent percent."
103: }
104:
105: #=================================
106: # Main program
107: initialize
108:
109: subject=$(choose_subj)
110: [[ $? -eq 0 ]] || exit 2
111:
112: cd $subject || exit 2
113: echo
114: scramble
115:
116: for ques in ${questions[*]};do
117: ask $ques
118: result=$?
119: (( num_ques=num_ques+1 ))
120: if [[ $result == 1 ]];then
121: ((num_correct+=1))
122: fi
123: echo
124: sleep ${QUIZDELAY:=1}
125: done
126:
127: summarize
128: exit 0
129:
130: set +o xtrace
# 照着书上拍的代码,信息量好大,等下细细研究下
3、查找系统中所有大于500M的文件,并把这些文件名写到一个文本文件中 并统计其个数
a) 查找大于500M的文件: find –size +500000000c –type f
b) 文件名写入到文本文件: find –size +500000000c –type f > files.dat 或者 find –size +500000000c –type f | tee files.dat 区别在于tee会在重定向输出的同时,在屏幕上同步显示输出内容
c) 统计文件个数:使用wc,每个文件名一行,故 wc –l