一. $变量的使用
study1.sh脚本代码如下:
#!/bash/bin
#打印adc这个变量,比如主进程定义一个变量: export abc=10
echo $abc
#打印第一个变量
echo $1
#打印第二个变量
echo $2
echo "--------"
# $#表示参数个数,打印参数个数
echo $#
# $*相当于java的list.toString(),获取以字符串返回所有参数元素
echo $*
# 相当于java的list.toArray(),返回以数组形式的所有参数元素
echo $@
程序结果:
$? 上一个命令的执行是否成功
展示参数列表:
$@ 独立参数
$* 当做整体
二. if,case条件判断
1.写一个成绩判断程序,当分数x不低于90,打印A,不低于80,打印B,不低于60,打印C,否则为D
if代码
if([ $1 -ge 90 ]);
then
echo 'A';
elif([ $1 -ge 80 ]);
then
echo 'B';
elif([ $1 -ge 60 ]);
then
echo 'C';
else
echo 'D';
fi
2.写一个简易计算器,
比如:
输入参数3 + 5,输出8
输入参数11 \* 11,输出121
输入参数6 / 7,输出0
输入参数7 - 6,输出1
#!/bash/bin
var=$2
case $2 in
+)
var=$[$1+$3]
;;
-)
var=$[$1-$3]
;;
/)
var=$[$1/$3]
;;
\*)
var=$[$1*$3]
;;
# *是一个通配概念,相当于java的default
*)
var=error
;;
esac
#判断是否为整数,如果是整数,r将为空
#获取var的值,截掉第一个负号,截掉所有数字,r剩下为非数字
r=`echo $var | sed "s/^-//gi" | sed "s/[0-9]//gi"`
[ -n "$r" ] && echo 错误 && exit 1
echo $var
exit 0
三. for,while循环语句
1.计算1到100以内所有能被11整除的整数的和(while实现)
#!/bash/bin
var=1
sum=0
#从1到100循环
while [ $var -le 100 ]
do
#取余
mod=$[$var%11]
#判断是否能被11整除
if([ $mod -eq 0 ])
then
#求和
sum=$[sum+var]
fi
var=$[var+1]
done
#打印和
echo $sum
2.给定一张成绩表,计算每个同学的平均成绩(for实现)
成绩表如下
vi student
name java hadoop linux sql
qwer 60 67 75 98
tyzx 97 87 90 76
moon 79 91 92 87
fly 37 45 66 100
sky 56 96 97 61
check 70 61 52 39
此题用到了awk,需要了解awk可以查看我的另一篇博客,里面举了一个例子,比较容易看懂http://blog.csdn.net/m0_37681914/article/details/70156370
系统学习awk的话,可以查看博客
http://www.cnblogs.com/repository/archive/2011/05/13/2045927.html
awk的强大之处在于对文本处理了,在这一点上丝毫不逊色于java中String类.
#!/bash/bin
#研究了一下,awk中的对if条件判断和shell中语法还是有很大的区别,for也有一点点,请读者小心哦!
awk '
BEGIN{print "统计结果如下\nname\tavg";}
{
#统计成绩表
for(i=2;i<=NF;i++){
#成绩表第一行,则为各课程
if(NR==1)
ind[i]=$i;
#非第一行,则为成绩,score存入"课程名--该课程成绩和",stu存放学生成绩总分
else{
score[ind[i]]=score[ind[i]]+$i;
stu[$1]=stu[$1]+$i;
}
};
count=NF-1;
#打印学生平均成绩
if(NR!=1)
print $1 "\t" stu[$1]/count;
}
#打印课程成绩平均成绩
END{print "--------------------\ncourse\tavg";total=NR-1; for(i in score) print i "\t" score[i]/total}
' \
student
四. 使用shell编程完成小程序
现在,我们可以开始做一做bash小程序了!
在赛码网有bash题,可以刷
http://exercise.acmcoder.com/online/online_judge_list_all?konwledgeId=134
例题:
接下来,我们自己练练手吧!
1.求约德尔测试
http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1677&konwledgeId=134
编程的基本原则是从小点入手,本题的第一个小点,就是将第一列字符串转为010101011的二进制字符串,也就是字符串替换了,可以用sed,下面这张图是我一个一个测试的过程.
以上已经处理好字符串替换了,接下来应该思考匹配的问题了.
一开始我的思路是,首先统计有多少个数字a,将处理好的二进制串与输入的二进制串,做异或运算,将计算结果统计有r个1, 则 0的个数为b=a-r ; 最后b/a即可计算出结果.
相关测试如下:
#模拟两个2进制数
v1=2#10101101101
v2=2#10101101110
#异或运算,得到结果将为11,即两个位置有不同的数字
v3=$[$v1^$v2]
#按二进制打印(测试一下)
echo "obase=2;$v3"|bc
#统计有多少个1
r=`echo "obase=2;$v3"|bc | sed "s/0//gi" | wc -c`
#wc统计的时候包括了\n字符,需要减一
r=$[$r-1]
#统计原字符串有多少个字符
a=`echo $v1 | wc -c`
#统计的时候包含了2#,以及\n,需要减3
a=$[$a-3]
#计算有多少个相同的结果
b=$[$a-$r]
#计算最终结果
echo "scale=2;$b/$a" | bc
结果是预计之中!
但是却忽略一个很严重的问题,就是,数字是有界限的,题目要求是不超过1000位,二进制数的极限大概是63位(我没有测试过)
好吧,还是得一个一个来比较字符,写循环吧!
把字符串接着修改一下:
echo 'hello 123 #@1' | sed "s/[a-z|0-9]/1/gi" | sed "s/[^1]/0/gi" | sed "s/\([0-1]\)/\1 /gi"
这样就好切割字符串了
#!/bash/bin
#读取两个字符串
read -a s1
read -a s2
#将两个字符串转换为0 1 0 1这种类型格式
s3=`echo $s1 | sed "s/[a-z|0-9]/1/gi" | sed "s/[^1]/0/gi" | sed "s/\([0-1]\)/\1 /gi"`
s4=`echo $s2 | sed "s/\([0-1]\)/\1 /gi"`
#echo $s3
#echo $s4
#将字符串切割成只存储单个字符的数组
arr1=($s3)
arr2=($s4)
#获取数组长度
a=${#arr1[@]}
#b用于记录相同的个数
b=0
#循环判断处理
#`seq 0 $[$a-1]`生成从0到$a-1个序列
#等价于java中for(int i=0;i<a;i++)
for i in `seq 0 $[$a-1]`;do
#做对比判断
if([ $[arr1[i]] -eq $[arr2[i]] ]);
then
b=$[$b+1];
fi
done
#echo $b
#做最后的数值计算
b=$[$b*100]
result=$(echo "scale=2;$b/$a"|bc)
#按照格式调整结果
result=$result%
#输出结果
echo $result
这个代码已经比较接近理想结果了,只差最后一步了,就是四舍五入的问题了,比如0.666666应该输出成66.67%,而不是66.66%,当然,练到这里已经差不多了,后面有兴趣的同学可以做一做!
也可以参考:
http://blog.csdn.net/m0_37681914/article/details/78209177