Shell实战课后作业

编写一个脚本

在上节课抽奖的基础上增加如下功能

  • 编写一个完整的lucky.sh脚本
  • 支持设置参数一等奖1名,二等奖3名,三等奖6名
  • 已经抽中的人不再参与抽奖
#!/bin/bash 

lucky() {
	arr=()
	while read a
	do
		arr+=($a)
	done  ## 读取输入数据
	
	for count in {1..3}
	do
		## 3轮大循环,选出3个名次
		num=$count
		[ $count -eq 2 ] && num=3
		[ $count -eq 3 ] && num=6
		sub_arr=(${arr[@]})      ## 循环筛选数组
		sub_arr_cp=(${arr[@]})	 ## 人员留存数组,防止数组下标变化
		while [ ${#sub_arr[@]} -gt $num ]
		do
			data=(${sub_arr[@]})    ## 上一轮留存人员数组,用于复活
			for i in "${!sub_arr[@]}"
			do
				[ $((RANDOM%6)) -lt 3 ] && {
					unset sub_arr[$i]      ## 小于3淘汰
					[ ${#sub_arr[@]} -ge $num ] && unset sub_arr_cp[$i]  ## 循环筛选数组人数大于等于获奖人数,就删除人员留存数组相应人员
					[ ${#sub_arr_cp[@]} -eq $num ] && break		## 当人员留存数等于获奖人数,跳出循环
				}
			done
			
			[ ${#sub_arr[@]} -lt $num ] && sub_arr=(${data[@]})		## 循环筛选数组人数小于获奖人数,复活
		done
		echo "$count等奖: ${sub_arr_cp[@]}"
		for index in ${!sub_arr_cp[@]}   ## 遍历每轮获奖人员的下标,然后在总数组中删除对应人员,不参与下一轮筛选
		do
			unset arr[$index]
		done
		echo -e "淘汰人员:${arr[@]}\n"
		arr=(${arr[@]})    ## 把删除获奖人员后的数组赋值给总数组
	done	
}

课后作业

1.创建文件 lucky.sh:

#!/bin/bash
#需要给默认值,不然用于数组的时候,会默认有一个初始元素
all=() 
sub_temp=() 
sub=() 
index=0 
#已经中奖的人存放数组
people=()
#多行模式支持选手名字带有空格
while read line; do
    all+=("$line")
done
#存放初始化的人员数据
people_temp=(${all[@]})

#进行10个人抽奖
for c in 0 1 2 3 4 5 6 7 8 9; do 

    #判断是否已经中奖了
    for i in ${!people_temp[@]}; do
        if [ ${people_temp[i]} == ${people[c-1]} ] ; then
            echo "已经中奖的:"${people_temp[i]};
            unset people_temp[i];
	    break;
        else
            continue; fi
    done
   
    echo "有资格进行下一轮的:"
    echo "${people_temp[*]}"
    echo ""

    #存放未中奖数据进行下一轮的抽奖
    all=(${people_temp[@]})

    #单行的时候,默认空格区分每个选手
    ((${#all[@]} == 1)) && all=($all)
    #用于数据处理,不影响原来的all
    sub=("${all[@]}")

    while true; do
        echo "index=$index count=${#sub[@]} sub=${sub[@]}"
        ((index++))
        #用于复活上一轮的种子
        sub_temp=(${sub[@]})

        for i in "${!sub[@]}"; do
            ((RANDOM % 6 + 1 > 3)) || unset sub[$i]
        done

        ((${#sub[@]} == 1)) && {
            echo winner=${sub[@]};
            echo "";
            #把中奖的人放到people数字
            people[c]=${sub[@]};
            break;
        }
        #复活上一轮
        ((${#sub[@]} == 0)) && { sub=(${sub_temp[@]}); }
    done
done
#输出中奖的人
    echo "一等奖:"${people[0]}
    echo "二等奖:"${people[1]},${people[2]},${people[3]}
    echo "三等奖:"${people[4]},${people[5]},${people[6]},${people[7]},${people[8]},${people[9]}


2.使用命令

···
seq 1 100 | ./lucky.sh
···

lucky.sh

#!/bin/bash

#需要给默认值,不然用于数组的时候,会默认有一个初始元素
all=() sub_temp=() sub=() index=0 luckyguys=() third_prize=() second_prize=()

#多行模式支持选手名字带有空格
while read line; do
    all+=("$line")
done
#单行的时候,默认空格区分每个选手
((${#all[@]} == 1)) && all=($all)
#用于数据处理,不影响原来的all
sub=("${all[@]}")
# 抽取幸运十人
while true; do
    echo "index=$index count=${#sub[@]} sub=${sub[@]}"
    ((index++))
    #用于复活上一轮的种子
    sub_temp=(${sub[@]})
    # 骰子数小于4的淘汰
    for i in "${!sub[@]}"; do
        ((RANDOM % 6 + 1 > 3)) || unset sub[$i]
    done

    ((${#sub[@]} == 10)) && {
        echo
        luckyguys=(${sub[@]})
        # echo winner=${luckyguys[@]}
        break
    }
    #复活上一轮
    ((${#sub[@]} < 10)) && { sub=(${sub_temp[@]}); }
done
# 在幸运十人中抽取六人作为三等奖的获得者
while true; do
    echo "index=$index count=${#sub[@]} sub=${sub[@]}"
    ((index++))
    #用于复活上一轮的种子
    sub=(${luckyguys[@]})
    sub_temp=(${sub[@]})

    for i in "${!sub[@]}"; do
        ((RANDOM % 6 + 1 > 3)) || unset sub[$i]
    done

    ((${#sub[@]} == 6)) && {
        echo
        third_prize=(${sub[@]})
        # echo winner 3 =${third_prize[@]}
        break
    }
    #复活上一轮
    ((${#sub[@]} < 6)) && { sub=(${sub_temp[@]}); }
done
# 去除已中奖的六人
for ADEL in "${third_prize[@]}"; do
    for i in "${!luckyguys[@]}"; do
        if [[ ${luckyguys[$i]} = ${ADEL} ]]; then
            unset luckyguys[$i]
        fi
    done
done
# 在剩余的四人当中抽取3人作为二等奖的获得者
while true; do
    echo "index=$index count=${#sub[@]} sub=${sub[@]}"
    ((index++))
    #用于复活上一轮的种子
    sub=(${luckyguys[@]})
    sub_temp=(${sub[@]})

    for i in "${!sub[@]}"; do
        ((RANDOM % 6 + 1 > 3)) || unset sub[$i]
    done

    ((${#sub[@]} == 3)) && {
        echo
        second_prize=(${sub[@]})
        # echo winner 3 =${second_prize[@]}
        break
    }
    #复活上一轮
    ((${#sub[@]} < 3)) && { sub=(${sub_temp[@]}); }
done
# 剩余的一人为一等奖获得者
for ADEL in "${second_prize[@]}"; do
    for i in "${!luckyguys[@]}"; do
        if [[ ${luckyguys[$i]} = ${ADEL} ]]; then
            unset luckyguys[$i]
        fi
    done
done

echo "一等奖:"${luckyguys[@]}
echo "二等奖:"${second_prize[@]}
echo "三等奖:"${third_prize[@]}

抽奖效果

使用方法

  • 创建lucky.sh
  • 复制代码到lucky.sh中并保存
  • 在包含lucky.sh文件路径下输入"seq 1 100 | ./lucky.sh"运行
#!/usr/bin/bash
lucky() {
    flag=0
    #需要给默认值,不然用于数组的时候,会默认有一个初始元素
    local all=() sub_temp=() sub=() index=0 win=() winner=()
    #设置不同奖项人数
    win[1]=1 win[2]=3 win[3]=6
    #多行模式支持选手名字带有空格
    while read line; do
        all+=("$line")
    done
    #单行的时候,默认空格区分每个选手
    ((${#all[@]} == 1)) && all=($all)
    echo allpeople=${all[@]}
    #用于数据处理,不影响原来的all
    for j in "${!win[@]}"; do
        sub=("${all[@]}")
        echo
        echo "$j等奖名额总共有:${win[j]}人"
        while true; do
            (($flag == 1)) && { echo "index=$index count=${#sub[@]} sub=${sub[@]}"; }
            ((index++))
            #用于复活上一轮的种子
            sub_temp=(${sub[@]})
            for i in "${!sub[@]}"; do
                ((RANDOM % 6 + 1 > 3)) || unset sub[$i]
            done
            ((${#sub[@]} == ${win[j]})) && { 
                for k in "${sub[@]}"; do 
                    unset all[$k-1]
                done
                winner[$j]=${sub[@]}
                echo "$j等奖中奖的有:${winner[$j]}"
                break
            }
            #复活上一轮
            ((${#sub[@]} < ${win[j]})) && { sub=(${sub_temp[@]}); }
        done
        echo "剩余未中奖人员名单如下:${all[@]}"
    done
    echo "----所有中奖人员名单如下----"
    echo "1等奖中奖的有:${winner[1]}"
    echo "2等奖中奖的有:${winner[2]}"
    echo "3等奖中奖的有:${winner[3]}"
}
seq 1 100 | lucky

抽奖效果

1 Like

完整的lucky.sh脚本

active=()
for j in `seq 1 100`;do
        active+=($j)
done
while ((${#active[@]} != 1));do
    if ((${#active[@]} >= 2));then
        sub=()
        sub_tmp=()
        for i in "${active[@]}";do
            if ((RANDOM%6+1>3));then    #满足条件的进入下一轮,未满足进入候补席
                sub+=($i)
            else sub_tmp+=($i)
            fi
        done
        active=(${sub[@]})
    elif ((${#active[@]} == 0 ));then    #复活候补席
        active=(${sub_tmp[@]})
    fi
    echo ${active[@]}
done
# seq 100| lucky![1|800x666](upload://7fN4Sn1358xRyUnkfOJj854XsTG.png) 
lucky(){
    #需要给默认值,不然用于数组的时候,会默认有一个初始元素
    local all=() sub_temp=() sub=() index=0 ml=()
    NO_ONE_p=$NO_ONE
    NO_TWO_p=$NO_TWO
    NO_THREE_p=$NO_THREE
    total_p=$(($NO_ONE_p+$NO_TWO_p+$NO_THREE_p))
    
    #多行模式支持选手名字带有空格
    while read line; do
        all+=("$line")
    done
    #单行的时候,默认空格区分每个选手
    ((${#all[@]} == 1)) && all=($all)
    #用于数据处理,不影响原来的all
    sub=("${all[@]}")

    while true; do
        echo "index=$index count=${#sub[@]} sub=${sub[@]}"
        ((index++))
        #用于复活上一轮的种子
        sub_temp=(${sub[@]})

        for i in "${!sub[@]}"; do
            ((RANDOM % 6 + 1 > 3)) || {
                ml+=(${sub[$i]})
                unset sub[$i]
            }
        done

        ((${#sub[@]} == 1)) && {
            echo
            # echo winner=${sub[@]}
            break
        }
        #复活上一轮
        ((${#sub[@]} == 0)) && { sub=(${sub_temp[@]}); }
    done
    echo -e "the first prize person number is: $NO_ONE_p \nthe second prize person number is: $NO_TWO_p \nthe third prize person number is: $NO_THREE_p \nthe total prize person .N is $total_p"
    echo -e "The elimination order of the first place is not included in the participants :\n${ml[@]}"
    echo "------------------------"
    echo "winner :"${sub[@]}
    echo "second prize :"${ml[@]: -$NO_TWO_p}
    echo "third prize :"${ml[@]: -(($total_p-1)):NO_THREE_p}
}
NO_ONE=1
NO_TWO=3
NO_THREE=6

lucky() {
    #需要给默认值,不然用于数组的时候,会默认有一个初始元素
    echo "开始抽奖"
    local all=()      # 总抽奖人数
    local sub_temp=() # 保证晋级数据
    local sub=()      # 实际的总抽奖人数
    local win_name=() # 中奖人数
    local i=0
    while read line; do
        all+=($line)
    done
    ((${#all[@]} == 1)) && all=($all)
    sub=("${all[@]}")
    echo ${sub[@]}
    while true; do
        index=0
        local add_name=()  # 紧急失败的抽奖人数
        local lose_name=() # 保证失败数据
        while true; do
            echo "num=$i index=$index count=${#sub[@]} sub=${sub[@]}"
            ((index++))
            sub_temp=(${sub[@]})
            lose_name=(${add_name[@]})
            for a in "${!sub[@]}"; do
                ((RANDOM % 6 + 1 > 3)) || {
                    add_name+=(${sub[$a]})
                    # echo ${add_name[@]}
                    unset sub[$a]
                }
            done
            # echo "数组值${sub[@]}"
            # echo "数组长度${#sub[@]}"
            aaa=`expr $i \* 3`
            if [ ${#sub[@]} == $aaa  ]; then
                echo
                win_name+=(${sub[@]})
                # echo ${win_name[@]}
                sub=(${add_name[@]})
                break
            fi
            if [ ${#sub[@]} -lt $aaa ]; then
                sub=(${sub_temp[@]})
                add_name=(${lose_name[@]})
            fi
        done
        ((i++))
        if [ $i == 3 ]; then
            break
        fi
    done
    echo "一等奖:${win_name[0]}"
    echo "二等奖:${win_name[1]},${win_name[2]},${win_name[3]}"
    echo "三等奖:${win_name[4]},${win_name[5]},${win_name[6]},${win_name[7]},${win_name[8]},${win_name[9]}"
}

luncy(){
    count=(1 2 3)    
    while (("${#count[@]}">0));do
        for n in "${!count[@]}";do
            seq 1 100|{
                all=();
                sub=();
                while read line;do
                    all+=($line)
                done
                while (("${#all[@]}">"${count[$n]}"));do
                    sub=("${all[@]}")
                    for i in "${!all[@]}";do
                        ((RANDOM%6+1<=3)) && unset all[$i]
                    done
                    (("${#all[@]}"<"${count[$n]}")) && all=("${sub[@]}")
                done
                echo "${count[$n]}""等奖的获得者是:""${all[@]}"
            }           
            unset count[$n]
        done
    done
}
#! /bin/bash

lucky_draw(){

    #将所有参与抽奖的人保存在一个数组people[]中

    seq 100 | { people=(); 

        while read line;do 

            people+=($line);

    done;

    lucky_guy=()

    index=0

    #打印参与抽奖的人

    echo "所有参赛人员如下:"${people[@]}; 

    while ((${#people[@]} >10));do

    #    ((index+=1))

        lucky_guy=("${people[@]}")

        #取数组people的下标,赋值给i,并且掷色子,点数小于等于3的人,直接剔除

        for i in "${!people[@]}";do

            ((RANDOM%6 +1 <= 3)) && unset people[$i]

        done

        #复活轮次,若最后一次取到到人数小于10,就返回上一轮次重新抽奖

        ((${#people[@]} < 10)) && people=("${lucky_guy[@]}")

    done

    #打印获奖的前十人

    echo "进入下一轮比赛的人员如下:"${people[@]}

    #将所有获奖的10位存在数组sec_lucy_boy中待抽取二等奖时使用

    sec_lucy_boy=("${people[@]}")

    all_lucy_boy=()

        

    #从前十名中抽取第一名,获得一等奖。

    while ((${#people[@]} >1));do

        ((index+=1))

        all_lucy_boy=("${people[@]}")

        #取数组people的下标,赋值给i,并且掷色子,点数小于等于3的人,直接剔除

        for i in "${!people[@]}";do

            ((RANDOM%6 +1 <= 3)) && unset people[$i]

        done

        #复活轮次

        ((${#people[@]} == 0)) && people=("${all_lucy_boy[@]}")

    done

    #打印一等奖获得者1名

    echo "一等奖获得者:"${people[@]}

    #除去一等奖获得者

    for ADEL in "${people[@]}"; do

        for i in "${!sec_lucy_boy[@]}"; do

            if [[ ${sec_lucy_boy[$i]} = ${ADEL} ]]; then

            unset sec_lucy_boy[$i]

            fi

        done

    done

    #将二等奖三等奖参赛人员保存到数组last_lucy_boy中

    last_lucy_boy=("${sec_lucy_boy[@]}")   

    three_lucy_boy=()  

    #从剩下9人中抽取前三名获得二等奖 

    while ((${#sec_lucy_boy[@]} >3));do

        three_lucy_boy=("${sec_lucy_boy[@]}")

        #取数组people的下标,赋值给i,并且掷色子,点数小于等于3的人,直接剔除

        for i in "${!sec_lucy_boy[@]}";do

            ((RANDOM%6 +1 <= 3)) && unset sec_lucy_boy[$i]

        done

        #复活轮次

        ((${#sec_lucy_boy[@]} < 3)) && sec_lucy_boy=("${three_lucy_boy[@]}")

    done

    #打印二等奖三名

    echo "二等奖获得者:"${sec_lucy_boy[@]}

    #从剩下获奖的9人中除去前第二名,剩余六人获得三等奖

    for ADEL in "${sec_lucy_boy[@]}"; do

        for i in "${!last_lucy_boy[@]}"; do

            if [[ ${last_lucy_boy[$i]} = ${ADEL} ]]; then

            unset last_lucy_boy[$i]

            fi

        done

    done 

    #打印三等奖六名

    echo "三等奖获得者:"${last_lucy_boy[@]}

    }

}
#!/bin/bash

all=()  #存储所有的所有的选手

lucky_people=() #存储中奖的选手

index=0 #初始化一个计数器

while read line; do
    all+=($line)
done

echo ${all[@]}  #输出所有选手的信息
echo "++++++所有参赛选手信息如上++++++"
echo ""

first_people=()
first_people=("${all[@]}")  #备份所有选手的信息

#筛选出一等奖得主
while ((${#first_people[@]}>1)); do
    ((index+=1))

    first_sub=("${first_people[@]}")    #本轮参与淘汰的选手

    #淘汰不符合条件的选手
    for i in "${!first_people[@]}"; do
        ((RANDOM%6+1<3)) && unset first_people[$i]
    done

    echo "当前剩余选手为:${first_people[@]}"    #输出当前剩余选手信息

    #复活上一轮选手信息
    ((${#first_people[@]}==0)) && { first_people=("${first_sub[@]}"); }
done

#将一等奖得主存储在数组中
lucky_people+=("${first_people[@]}")
echo "一等奖得主为:${lucky_people[@]}"
echo "++++++第一轮筛选结束,诞生一等奖选手++++++"
echo ""
echo ""     



#筛选出二等奖得主

second_people=()
second_people=("${all[@]}") #备份所有选手的信息

#过滤已获奖选手
for s in "${!second_people[@]}"; do
    for l in "${!lucky_people[@]}"; do
        ((${second_people[$s]}==${lucky_people[$l]})) && unset second_people[$s]
        break
    done
done

echo "第二轮参赛选手信息为:${second_people[@]}"
echo ""

while ((${#second_people[@]}>3)); do
    ((index+=1))

    second_sub=("${second_people[@]}" )  #本轮参与淘汰的选手
    
    #淘汰不符合条件的选手
    for i in "${!second_people[@]}"; do
        ((RANDOM%6+1<3)) && unset second_people[$i]
    done

    echo "当前剩余参赛选手为:${second_people[@]}"

    #复活上一轮参赛选手
    ((${#second_people[@]}<3)) && { second_people=("${second_sub[@]}"); }
done 
echo "二等奖得主为:${second_people[@]}"

#将二等奖的得主存储在数组中
lucky_people+=("${second_people[@]}")
echo "一等奖、二等奖得主为:${lucky_people[@]}"
echo "++++++第二轮筛选结束,诞生一等奖、二等奖得主++++++"
echo ""
echo ""


# #筛选出三等奖得主
third_people=()
third_people=("${all[@]}")   #备份所有选手的信息

for t in "${third_people[@]}"; do
    for l in "${!lucky_people[@]}"; do
        (( ${t} == ${lucky_people[$l]} )) && unset third_people[$t]
    done
done

echo "第三轮参赛选手信息为:${third_people[@]}"
echo ""

while ((${#third_people[@]}>6)); do
    ((index+=1))

    third_sub=("${third_people[@]}")    #本轮参与淘汰的选手

    #淘汰不符合条件的选手
    for i in "${!third_people[@]}"; do
        ((RANDOM%6+1<3)) && unset third_people[$i]
    done

    echo "当前剩余参赛选手为:${third_people[@]}"

    #复活上一轮参赛选手
    ((${#third_people[@]}<6)) && { third_people=("${third_sub[@]}"); }

done

echo "三等奖得主为:${third_people[@]}"

#将三等奖得主存储在数组中
lucky_people+=("${third_people[@]}")
echo "++++++第三轮筛选结束,诞生十名幸运选手++++++"
echo ""
echo ""

#输出中奖人
echo "++++++++获奖名单如下++++++++"
echo "一等奖获得者为:"${lucky_people[0]}
echo "二等奖获得者为:"${lucky_people[1]},${lucky_people[2]},${lucky_people[3]}
echo "三等奖获得者为:"${lucky_people[4]},${lucky_people[5]},${lucky_people[6]},${lucky_people[7]},${lucky_people[8]},${lucky_people[9]}

运行方法:seq 1 100 | ./lucky.sh

image

lucky.sh

lucky() {
    arr=()
    tmp=()
    sub_arr=()
    ind=0

    while read line; do
        arr+=($line)
    done

    ((${#arr[@]} < 10)) && echo "人数少于10,不足以抽奖!" && return
    sub_arr=(${arr[@]})

    # 定义1、2、3等奖的获奖人数
    nofw=(1 3 6)
    for l in {2..0}; do
        cnt=${nofw[$l]}
        echo "抽取 $(($l + 1)) 等奖,共 $cnt 名:"
        winners=()

        while [ $cnt -gt 0 ]; do
            # 缓存当前的剩余未中奖人员数组,抽奖完成后更新
            tmp=(${sub_arr[@]})
            draw=(${tmp[@]})
            while true; do
                # 备份本轮人员,当本轮都未中奖时复活
                backup=(${tmp[@]})

                # 剩余1人时即中奖,同时根据当前索引删除缓存数组中的值
                ((${#draw[@]} == 1)) && {
                    ind=${!draw[@]}
                    unset tmp[$ind]
                    winner=${draw[@]}
                    break
                }

                # 抽奖
                for i in ${!draw[@]}; do
                    (($RANDOM % 6 + 1 > 3)) || unset draw[$i]
                done

                # 都未中奖时复活
                ((${#draw[@]} == 0)) && {
                    draw=(${backup[@]})
                }
            done
            # 从缓存更新子数组
            sub_arr=(${tmp[@]})
            winners+=($winner)
            ((cnt--))
        done

        echo " -- 获得 $(($l + 1)) 等奖的是:${winners[@]}"
    done
}

执行结果:
[root@enterprise-cloud-dev tmp]# seq 1 100 | lucky
抽取 3 等奖,共 6 名:
– 获得 3 等奖的是:98 57 63 5 44 21
抽取 2 等奖,共 3 名:
– 获得 2 等奖的是:29 7 58
抽取 1 等奖,共 1 名:
– 获得 1 等奖的是:60

#!/bin/bash
person=()

# 一等奖中奖人员
first_number=()
first_prize=()

# 二等奖中奖人员
second_prize=()
second_number=()

# 三等奖中奖人员
thrid_prize=()
thrid_number=()

# 骰子数
dice_num=3

# 输入机会
input_number=3
while [ $input_number -gt 0 ]; do

    read -p "请输入大于或等于10的整数:" num
    if [ $num -lt 10 -a $((num % 10)) -gt 0 ]; then
        ((input_number--))
        if [ $input_number -eq 0 ]; then
            echo "输入机会用完,程序退出"
        else
            echo "输入错误,请重新输入, 你还有"$input_number"次机会"

        fi
    else
        break
    fi
done

# 抽奖人员初始化
for i in $(seq 1 $num); do
    person+=($i)
done

while [ ${#person[*]} -gt 1 ]; do
    for ((i = 0; i < ${#person[*]}; i++)); do
        # 第一轮抽3等奖
        if [ $((RANDOM % 6 + 1)) -gt $dice_num ]; then
            # 随机抽取获奖人员
            rand_num=$((RANDOM % $num))
            # 判断随机数是否重复
            if [ ${person[$rand_num]} ]; then
                thrid_prize+=(${person[$rand_num]})
                unset person[$rand_num]
                if [ ${#thrid_prize[*]} -eq 6 ]; then
                    echo "第三等奖获奖人员名单:${thrid_prize[*]}"
                    second_number=(${person[*]})
                    break
                fi
            else
                continue
            fi

        fi
    done

    # 判断是否需要复活
    if [ ${#thrid_prize[*]} -le 6 ]; then
        person=(${person[*]})
    fi
done

while [ ${#second_number[*]} -gt 1 ]; do
    for ((i = 0; i < ${#second_number[*]}; i++)); do
        if [ $((RANDOM % 6 + 1)) -gt $dice_num ]; then

            rand_num=$((RANDOM % $num))
            if [ ${second_number[$rand_num]} ]; then
                second_prize+=(${second_number[$rand_num]})
                unset second_number[$rand_num]
                if [ ${#second_prize[*]} -eq 3 ]; then
                    echo "第二等奖获奖人员名单:${second_prize[*]}"
                    first_number=(${second_number[*]})
                    break
                fi
            else
                continue
            fi
        fi
    done
    if [ ${#second_prize[*]} -le 3 ]; then
        person=(${person[*]})
    fi
done

while [ ${#first_number[*]} -ge 1 ]; do
    for ((i = 0; i < ${#first_number[*]}; i++)); do
        if [ $((RANDOM % 6 + 1)) -gt $dice_num ]; then
            rand_num=$((RANDOM % $num))
            if [ ${first_number[$rand_num]} ]; then
                first_prize+=(${first_number[$rand_num]})
                unset first_number[$rand_num]
                if [ ${#first_prize[*]} -eq 1 ]; then
                    echo "第一等奖获奖人员名单:${first_prize[*]}"
                    break
                fi
            else
                continue
            fi
        fi
    done
    if [ ${#first_prize[*]} -lt 1 ]; then
        person=(${person[*]})
    fi
done

您好,seq 1 100 | ./lucky.sh, 这个语法是怎么理解的?不应该是./lucky.sh seq 1 100这样,参数都是在后面的吗?

seq 1 100 | ./lucky.sh

其实是两个命令呀,“|”是管道符,seq的输出结果作为“|”后面的输入。
如果‘./lucky.sh seq 1 100’这样写,就变成了打开lucky.sh这个文件而不是输入参数执行它了

完整的脚本代码:
#!/bin/bash
lucy2() {
    a1=($1)
    # echo "AAAAAAAAAAAAAAAAAAAAAAAAAA"
    # echo ${a1[@]}
    while true; do
        index1=0
        temp2=(${a1[@]})
        for i in ${temp2[@]}; do
            ((RANDOM % 6 + 1 > 3)) || unset temp2[$index1]
            ((index1++))
        done
        ((${#temp2[@]} == 0)) || a1=(${temp2[@]})
        ((${#temp2[@]} == 1)) && {
            echo ${temp2[@]}
            break
        }
    done
}
# echo $1
function lucyNow() {
    # echo "lucynow---------"
    inputn=($1)
    inputnTemp=(${inputn[@]]})
    # echo "ffffff"
    # echo ${inputn[@]}
    data1=$(lucy2 "${inputn[*]}")
    # echo "1212121212121111111111111111111"
    # echo $data1
    indexiii=0
    # echo "IIIIIIIIIIIIIIIIIIIIIIIIII"
    for k in ${inputnTemp[@]}; do
        if [ $k == $data1 ]; then
            unset inputnTemp[$indexiii]
        fi
        ((indexiii++))
    done
    # echo ${inputnTemp[@]}
    # echo "choose 2th"
    echo $data1
    echo ${inputnTemp[@]}
}
echo "1st choose winner:"
data0=(`seq 1 100`)
#echo ${#data0[@]}
Data=(`lucyNow "${data0[*]}"` )
echo ${Data[0]}
unset Data[0]
echo "2nd choose winner:"
select1=( `lucyNow "${Data[*]}"` )
# echo ${select1[@]}
# echo ${#select1[@]}
# echo "+++++++++++++"
echo ${select1[0]}
unset select1[0]
select2=( `lucyNow "${select1[*]}"`)
echo ${select2[0]}
unset select2[0]
select3=(`lucyNow "${select2[*]}"`)
echo ${select3[0]}
unset select3[0]
echo "3rd choose winner:"
select4=(`lucyNow "${select3[*]}"`)
echo ${select4[0]}
unset select4[0]
select5=(`lucyNow "${select4[*]}"`)
echo ${select5[0]}
unset select5[0]
select6=(`lucyNow "${select5[*]}"`)
echo ${select6[0]}
unset select6[0]
select7=(`lucyNow "${select6[*]}"`)
echo ${select7[0]}
unset select7[0]
select8=(`lucyNow "${select7[*]}"`)
echo ${select8[0]}
unset select8[0]
select9=(`lucyNow "${select8[*]}"`)
echo ${select9[0]}
unset select9[0]

运行结果:

[66755424@shell.ceshiren.com ~]$ ./last.sh
1st choose winner:
6
2nd choose winner:
96
37
77
3rd choose winner:
58
42
64
80
31
35

shell 语法太难受了,还不好调试。。。

#! /bin/bash

seq 20 | {
    all=() 
    loop=1
    while read line
    do
        all+=("$line")
    done
    echo ${all[*]}

    while true
    do
        echo "index=$loop count=${#all[*]} winner=${all[*]}"
        temp=${all[*]}    
        for i in "${!all[@]}"
        do
            if [ $(($RANDOM % 6 + 1)) -le 3 ]
            then
                unset all[$i]
            fi
        done
        if [ ${#all[*]} -eq 1 ]
        then
            echo "winner is ${all[*]}"
            break
        fi
        if [ ${#all[*]} -eq 0 ]
        then
            all=${temp[*]}
        fi
        loop=$((loop+1))
    done
}

实现课上的lucky的时候写的这一段,有两个问题

  1. 为什么有时候运行会出现这种情况,实在看不出来哪里出问题了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
index=1 count=20 winner=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
index=2 count=10 winner=4 5 8 9 11 13 14 15 17 19
index=3 count=3 winner=5 8 15
index=4 count=1 winner=5 8 15
winner is 5 8 15
  1. shell里面数组使用*@有什么区别,我在for循环里面使用*的时候就会报错:
lucky.sh: line 20: unset: `5': not a valid identifier
lucky.sh: line 20: unset: `6': not a valid identifier
lucky.sh: line 20: unset: `7': not a valid identifier
lucky.sh: line 20: unset: `8': not a valid identifier
lucky.sh: line 20: unset: `9': not a valid identifier
lucky.sh: line 20: unset: `10': not a valid identifier
lucky.sh: line 20: unset: `11': not a valid identifier
lucky.sh: line 20: unset: `12': not a valid identifier
lucky.sh: line 20: unset: `13': not a valid identifier

根据上面最后写出来的结果是这个,因为上面有bug所以这个也有。。。有时候还莫名奇妙死循环了。。。shell语法太难受了,用python写一遍转过来都写半天。。。

#! /bin/bash

seq 20 | {
    all=() 
    unlucky=()
    loop=1
    while read line
    do
        all+=("$line")
    done
    echo ${all[*]}
    unlucky=(${all[*]})
    first=()
    second=()
    third=()

    while true
    do
        echo "index=$loop count=${#all[*]} unlucky=${all[*]}"
        temp=${all[*]}    
        for i in "${!all[@]}"
        do
            if [ $(($RANDOM % 6 + 1)) -le 3 ]
            then
                unset all[$i]
            fi
        done

        if [ ${#all[@]} -eq 1 ]
        then
            if [ ${#third[*]} -lt 6 ]
            then
                third+=(${unlucky[$i]})
                unset unlucky[$i]
                all=(${unlucky[*]})
                continue
            elif [ ${#third[*]} -eq 6 -a ${#second[*]} -lt 3 ]
            then
                second+=(${all[*]})
                unset unlucky[$i]
                all=(${unlucky[*]})
                continue
            elif [ ${#second[*]} -eq 3 ]
            then
                first=${all[*]}
                break
            fi
        fi
        if [ ${#all[*]} -eq 0 ]
        then
            all=${temp[*]}
        fi
        loop=$((loop+1))
    done
    echo "third place is ${third[*]}"
    echo "second place is ${second[*]}"
    echo "winner is ${first[*]}"
}

问题1

  • 问题主要集中在 数组赋值的时候你没有加括号导致数组整体变成了一个字符串,就是这两句
    temp=${all[*]}
    all=${temp[*]}
    
  • 第一句导致每次存下来的temp都变成一个把所有数字拼在一起的字符串,而不是一个数组,平时因为用不到所以看不出来,但是如果结果为空需要重赛的时候,你的all获取到的是一个字符串,所以下一次就会将这个字符串整体当作一个数据来计算,那么长度肯定是1,导致输出的结果计数为1但是结果数字却是好几个
  • 如果只改动第一句,那么在第二句会出现相同的问题,导致问题还是会出现,所以需要两句都做修改

问题2

  • 如果你使用"${!all[*]}" 获取的结果就是一个含有全部下标的字符串,而不是每行一个单独的数据,所以循环只会进行一次,而i就是所有下标,下图示例可以看一下
    image

666​:+1: 还是python友好

    #! /bin/bash
            lucky(){
            seq 1 100 | {
                all=() 
                sub=()
                index=0
                luckies=() 
                person=()  
                awards=($1 $2 $3) 
                first_prize=()
                second_prize=()
                third_prize=() # 
                echo "awards:  ${awards[@]}"           
                while read line;do
                    all+=("$line")
                done           
                    for num in "${!awards[@]}";do          
                            for((n=0;n< "${awards[${num}]}";n++));do
                                    bk=("${all[@]}");                          
                                    while ((${#all[@]} > 1));do                                   
                                            sub=("${all[@]}"); 
                                            for i in "${!all[@]}";do
                                                    # echo $i;
                                                    ((RANDOM%6+1<=3)) && unset all[$i] 
                                            done
                                            #echo ids:"${!all[@]}";
                                            ((${#all[@]}==0)) && all=("${sub[@]}");                                 
                                    done                         
                                    per=("${all[@]}");                          
                                    if ((${num}==0));
                                      then first_prize+=("${per[@]}");
                                      elif ((${num}==1));
                                      then second_prize+=("${per[@]}");
                                      else third_prize+=("${per[@]}");
                                    fi
                                    for id in "${!bk[@]}";do
                                            ((bk[$id]==per[0])) && unset bk[$id];
                                    done
                                    #echo bk:"${bk[@]}";            
                                    all=("${bk[@]}");
                            done
                    done
                    echo first prize "${#first_prize[@]}" :"${first_prize[@]}";
                    echo second prize "${#second_prize[@]}" :"${second_prize[@]}";
                    echo third prize "${#third_prize[@]}" :"${third_prize[@]}";
            }
            }
            lucky $1 $2 $3