目的:主要是为了练习shell脚本的使用
1.首先在shell中创建一个抽奖名单,wx.txt文件,然后创建抽奖脚本,vim lottery.sh
2.编写脚本
@1.seed=cat wx.txt
或者seed=$(cat wx.txt)
在shell中执行命令并赋值给变量有两种方式,另外一种方式是用
(
)
,
例
如
a
=
(),例如a=
(),例如a=(cat /etc/issue)
另外一种是使用反引号
1)在shell脚本中使用反引号时,他本身就对\做了一层转义,如果你有需要匹配的\的情况的话,需要再次进行转义。所以在反引号中,两个转义符才是进行转义!
2)KaTeX parse error: Undefined control sequence: \的 at position 10: ()中则不需要考虑\̲的̲问题,与我们平常使用的一样:\…()是新的用法,我们推荐使用$()
@2. 这里先解释下代码:&&
((2==2))&&echo “chenrourou" 如果前面为1,就输出后面的值,一定要用括号括起来,不括起来就什么都不是,不会进行计算的;
&&操作的特性:类似于短路,用与的用法来写代码就非常简洁,很多大佬都用这种方法;
@3.
R
A
N
D
O
M
输
出
任
意
一
个
随
机
数
,
s
h
e
l
l
自
带
函
数
变
量
,
记
住
就
行
;
@
4.
e
c
h
o
“
RANDOM输出任意一个随机数,shell自带函数变量,记住就行; @4.echo “
RANDOM输出任意一个随机数,shell自带函数变量,记住就行;@4.echo“seed”加双引号和不加双引号的区别:
echo
s
e
e
d
(
会
打
印
成
一
行
,
每
行
以
空
格
分
隔
开
)
e
c
h
o
“
seed(会打印成一行,每行以空格分隔开) echo “
seed(会打印成一行,每行以空格分隔开)echo“seed”(会按文件中原来样式,一行一行打印)
@5.bug1分析:如果名字中间有空格,读取wx.txt中内容时,就会默认分隔成两个名字,因此要将读取文件改为:
seeds=$(while read line; do echo ${line// /…};done <wx.txt)
l
i
n
e
/
/
/
.
.
/
/
代
表
替
换
全
局
,
这
里
代
表
将
多
有
的
空
格
用
.
.
替
换
s
h
e
l
l
脚
本
编
写
一
节
有
提
到
b
u
g
2
分
析
:
{line// /..}//代表替换全局,这里代表将多有的空格用..替换 shell脚本编写一节有提到 bug2分析:
line///..//代表替换全局,这里代表将多有的空格用..替换shell脚本编写一节有提到bug2分析:seed没加双引号,只能统计一行,加了双引号就能统计多行 , 这里的$seeds不是数组而是以空格为分隔的字符
bug3分析:输出有空白,为什么会有空白呢,因为有的时候可能随机数中全是奇数
3.改进脚本,分析以上bug,去掉空白的脚本如下:
1)为什么要加local呢?(一定要注意)
因为不加local的话 count和seeds在bash里默认是全局的,如果是全局的,有好几个函数来调用,如果有一个函数中把seeds和count里面的数改变了,这里其他函数也都会改变;因为rand函数要递归,因此需要加local防止递归对变量的改变;
虽然递归影响效率,可以转化为for循环,但是使用for循环会使用好多行代码,不如递归简单
2)(( ))和[[ ]]的区别
(( ))的语法,是计算的语法,能够进行加减乘除运算;[[ ]]是用来条件判断的
3) :set number可以显示vim编辑器的行号
永久配置行号参考该博客
https://blog.csdn.net/technologyleader/article/details/90754268
键盘按“dd”运行vi删除行指令,之前光标移动的行被整行删除
4)while [[ $seeds == ‘’ ]] 该条命令’'中间咩有空格,要注意⚠️
4.为了防止抽中同一个同学多次,需要去重操作以及参数化
代码如下:
res(){
set=(1 2 3 4 5 6 7 8 9 10)
for i in KaTeX parse error: Can't use function '\textcircled' in math mode at position 14: \html@mathml{\̲t̲e̲x̲t̲c̲i̲r̲c̲l̲e̲d̲{\scriptsize R}…(rand)
while [[ $(is_repeat
t
m
p
)
]
]
;
d
o
t
m
p
=
tmp) ]];do tmp=
tmp)]];dotmp=(rand)
done
arrs[
i
]
=
i]=
i]=tmp
done
echo ${arrs[@]}
}
先分析is_repeat()函数,这里抽到的人的名字与已经抽到的数组中的名字进行对比去重,${arrs[@]}为数组中的名单,对该名单进行遍历,判断如果抽到的人和名单中的名字重复,就输出0,负责遍历完(注意是遍历完⚠️)之后输出1;这里的 1 是 i s r e p e a t ( ) 函 数 的 形 参 而 1是is_repeat()函数的形参而 1是isrepeat()函数的形参而tmp 是实参。
res()函数:对抽奖人数进行遍历(一次抽多少个中奖的人), 1 执 行 r a n d 函 数 并 赋 值 给 t m p 变 量 , 即 将 中 奖 的 人 的 名 字 赋 值 给 t m p 变 量 ; 判 断 当 中 奖 人 的 名 字 与 中 奖 名 单 ( 数 组 ) 重 复 的 时 候 , 继 续 执 行 r a n d 函 数 t m p = 1执行rand函数并赋值给tmp变量,即将中奖的人的名字赋值给tmp变量;判断当中奖人的名字与中奖名单(数组)重复的时候,继续执行rand函数tmp= 1执行rand函数并赋值给tmp变量,即将中奖的人的名字赋值给tmp变量;判断当中奖人的名字与中奖名单(数组)重复的时候,继续执行rand函数tmp=(rand),直到抽到的人名字与中奖名单中的名字不重复,则执行arrs[ i ] = i]= i]=tmp,将中奖的人加入中奖名单中,直到循环$i次为止,就可以打印出这个数组了,即中奖名单!
最后调用 res $1
运行该脚本,结果如下:
分类: linux命令和bash脚本