有空白的代码
#!/bin/bash
#bug 1
#seeds=`cat wx.txt`
#sed method
seeds=`sed -Ee 's/\s/,/g' wx.txt`
#wilie method
#seeds=`while read line; do echo ${line// /..}; done < wx.txt`
count=100
rand(){
while [ $count -ne 1 ] ; do
seeds=`for seed in $seeds ;do (( $RANDOM%2==0 )) && echo $seed; done`
count=`echo "$seeds" | wc -l`
count=$(($count+0))
done
echo $seeds
}
rand
代码思想
- 这段代码是想实现从wx.txt拿出数据,然后最终随机选出一位幸运观众,但是每次运行会概率性出现空白,也就是没有人被选出来的尴尬情况
思路
- 先读取到wx.txt全部数据,存放在seeds上
- 给一个计数器count,当seeds的count值等于1,才输出最后seeds的值
- 新的seeds值在for循环中,使用$RANDOM随机变量,这样,每个读取的名字,都会被随机的保留或者去除掉
- seeds的值会越来越小,因为新的seeds值都会被$RANDOM随机刷掉
- 当while循环中,count=1时,seeds的值也剩下一个了(一行)整个循环才会结束,就会打印最终的只有一个名字的seeds值了
具体的技术细节
-
seeds=`cat wx.txt`
- 反引号的作用是把cat wx.txt命令执行后在的结果赋值给seeds
- 有个问题,如果wx.txt有人名包含空格,比如"tong tong",最终打印运行完代码,打印的seeds值就是tong,而不是"tong tong"
- 解决的方法就是替换空格
-
seeds=`sed -Ee 's/\s/,/g' wx.txt`
- sed中的s//g的方法就可以把空格(\s)替换成",",后面有一个g,是把一行中全部的空格都换成逗号
- sed -eE是不对的写法,-Ee才是正确的写法
-
seeds=`while read line; do echo ${line// /..}; done < wx.txt`
- 这个方法暂时还看不懂
-
while [ $count -ne 1 ]
- 我的实现方式和老师不一样,[] 表示里面只能是数字的对比,所以$count和1都必须是数字才行
- 老师是使用[[ $count == 1 ]],[[]]表示的是字符串的对比
- 如果count一开始不赋值,那么count会默认一个非数字的值,所以在while [ $count -ne 1 ]的代码之前,加上count=100,只要count不是1都行
-
seeds=`for seed in $seeds ;do (( $RANDOM%2==0 )) && echo $seed; done`
- 需要注意这里的执行顺序,是先把for seed in $seeds ;do (( $RANDOM%2==0 )) && echo $seed; done的命令执行了,输出了内容之后,再把内容全部赋值给seeds
- 下面的执行效果就告诉我们,执行了for((i=0;i<3;i++)); do echo i ;done 屏幕打印了全部的值,然后再把这些值赋给a
- echo “$a” 才会按照行来打印a的值,echo $a 打印的每个值都用空格隔开显示,只显示一行
[root@VM_0_8_centos shizhan]# for((i=0;i<3;i++)); do echo $i ;done
0
1
2
[root@VM_0_8_centos shizhan]# a=`for((i=0;i<3;i++)); do echo $i ;done`
[root@VM_0_8_centos shizhan]# echo "$a"
0
1
2
[root@VM_0_8_centos shizhan]# echo $a
0 1 2
-
count=`echo "$seeds" | wc -l`
- 统计seeds值有多少行,一行代表一个用户
-
count=$(($count+0))
- f 这里是把字符串转化成数字
- seed=
ls
,反引号的命令赋值永远都是字符串,就是ls的结果是数字,也是字符串
- ``` count = `ls````
- 赋值运算千万不要有空格
-
为什么会有空白的产生
- 因为seeds的产生,是通过random来的,当seeds只有2个名字,radmon都是奇数,那么seeds的值就等于0了,但即使seeds的值等于0,经过 wc -l之后,这个值还是为1,符合while的条件判断,就不运行了
修复空白的代码
#!/bin/bash
rand(){
#local count
#local seeds
seeds=`sed -Ee 's/\s/,/g' wx.txt`
count=0
while [ $count -ne 1 ] ; do
seeds=`for seed in $seeds ;do (( $RANDOM%2==0 )) && echo $seed; done`
count=`echo "$seeds" | wc -l`
count=$(($count+0))
done
if [[ $seeds == "" ]];then
rand
else
echo $seeds
fi
}
rand
思路和技术
- 加一个判断,当seeds的值为空,就再次递归使用rand函数的,直到seeds不为空,就输出seeds的值出来
去除重复,并手动输出多个中奖号码
#!/bin/bash
rand(){
seeds=`sed -Ee 's/\s/,/g' wx.txt`
count=0
while [ $count -ne 1 ] ; do
seeds=`for seed in $seeds ;do (( $RANDOM%2==0 )) && echo $seed; done`
count=`echo "$seeds" | wc -l`
count=$(($count+0))
done
if [[ $seeds == "" ]];then
rand
else
echo $seeds
fi
}
res(){
for((i=0;i<10;i++));do
tmp=`rand`
while [[ `is_repeat $tmp` == 0 ]];do
tmp=`rand`
done
arrs[$i]=$tmp
done
echo ${arrs[@]}
}
is_repeat(){
for arr in ${arrs[@]};do
if [[ $1 == $arr ]];then
echo 0
return 0
fi
done
es
思路
- res函数是主函数,10个表示抽取10个人出来
- is_repeat函数是判断当前需要添加的新值,在seeds中是否有重复的,没有重复才允许添加进去
具体的技术细节
-
for((i=0;i<10;i++));do
- 表示我们要抽10个人,循环10次,一次取一个人出来
- is_repeat $tmp是看看tmp的值是否在arrs里面,如果不在,就可以添加到arrs里面,如果在,就循环获取tmp的值,直到tmp的值渣arrs数组中是唯一的
while [[ `is_repeat $tmp` == 0 ]];do
tmp=`rand`
done
arrs[$i]=$tmp
- 遍历获取到当前arr的值,$1是指is_repeat $tmp的$tmp,如果tmp在数值,整个函数的结果就返回0了,
for arr in ${arrs[@]};do
if [[ $1 == $arr ]];then
echo 0
return 0
fi
参数化
res(){
for((i=0;i<$1;i++));do
tmp=`rand`
while [[ `is_repeat $tmp` == 0 ]];do
tmp=`rand`
done
arrs[$i]=$tmp
done
echo ${arrs[@]}
}
res 4
思路
- 就是之前i<$10的值变成了i<$1,最后通过运行res 4,来决定抽取的人数,4表示抽取4个人