사례 11. 인원 조별

요 구 는 다음 과 같 습 니 다.
1) 총 72 명 이 라 고 가정 (한 명의 인원 명단 을 제공 하고 이름 은 중국어 병 음)
2) 7 개 조로 나 눠 야 한다
3) 스 크 립 트 를 실행 할 때마다 결과 가 달라 야 한 다 는 임 의 성 을 확보 해 야 한다.
지식 포인트 1: 난수 생 성
Linux 시스템 에 내 장 된 변수 RANDOM 이 있 습 니 다. 이것 은 무 작위 숫자 입 니 다. 용법 은 다음 과 같 습 니 다.
# echo $RANDOM
17023

이 RANDOM 변수 수치 범 위 는 0 - 32767 입 니 다. 더 긴 랜 덤 수 를 가 져 오 려 면 여러 개의 RANDOM 을 통 해 중첩 할 수 있 습 니 다. 예 를 들 어:
# echo $RANDOM$RANDOM
2239928526

두 번 째 방법 은 date 명령 을 사용 하 는 것 입 니 다. date 는% N 이 있 습 니 다. 현재 시간의 초 를 인쇄 할 수 있 습 니 다. 단 위 는 나 초 입 니 다.
# date +%N
594253932

세 번 째 방법 은 시스템 의 특수 장치/dev/urandom 을 읽 는 것 입 니 다. 다음 과 같 습 니 다.
# head -100 /dev/urandom|cksum
2604766758 24408

이/dev/urandom 은 무 작위 수 를 만 드 는 특수 장치 로 바 이 너 리 이기 때문에 cat 나 head 를 직접 만 들 수 는 없 지만 파 이 프 를 추가 하여 결 과 를 cksum 에 게 건 네 줄 수 있 습 니 다.cksum 은 파일 이나 문 자 를 검사 하 는 도구 로 두 개의 숫자 문자열 을 만 들 수 있 습 니 다.파이프 앞의 문자열 은 무 작위 이기 때문에 이 숫자 문자열 도 자 연 스 럽 게 무 작위 입 니 다.
우 리 는 첫 번 째 숫자 꼬치 만 가 져 오 면 되 기 때문에 awk 로 처리 해 야 합 니 다.
# head -100 /dev/urandom|cksum|awk '{print $1}'
2194071486

물론, cksum 명령 도 문자열 의 검사 값 을 계산 하여 무 작위 수 를 얻 을 수 있 습 니 다. 다음 과 같 습 니 다.
# echo "Zhangsan"|cksum |awk '{print $1}'
2674179083

지식 포인트 2: 순 서 를 흐 트 러 뜨리 기
사례 는 임 의 성 을 요구 하기 때문에 제 시 된 인원 명단 은 순 서 를 흐 트 러 뜨리 는 것 이 좋 습 니 다. 그러면 매번 스 크 립 트 를 실행 할 때마다 임 의 성 을 확보 하고 shuf 명령 을 사용 하여 실현 할 수 있 습 니 다.
# seq 1 5 |shuf
2
4
5
1
3
# seq 1 5 |shuf
3
4
5
1
2

매번 다른 서열 을 얻는다.파일 에 직접 작용 할 수도 있 고 파일 의 줄 순 서 를 흐 트 러 뜨 릴 수도 있 습 니 다.
# shuf /etc/passwd |head -n2
user_82:x:1102:100::/home/user_82:/bin/bash
user_93:x:1113:100::/home/user_93:/bin/bash
# shuf /etc/passwd |head -n2
user_13:x:1033:100::/home/user_13:/bin/bash
user_31:x:1051:100::/home/user_31:/bin/bash

shuf 명령 은 줄 순 서 를 흐 트 러 뜨 릴 뿐 줄 안의 문자 위 치 를 바 꾸 지 않 습 니 다.
지식 포인트 3: 셸 의 숫자 반올림
셸 의 출발 연산 은 직접 소 수 를 버 릴 것 이다. 예 를 들 어 1.9 는 1 로 직접적 으로 합 리 적 이지 않 고 아래 의 방법 은 반올림 을 실현 할 수 있다.
#!/bin/bash
#          ,    $1    ,$2   
div()
{
  n=`echo "scale=1;$1/$2" |bc`
  n1=`echo "sclae=1;$n+0.5" |bc`
  echo $n1 |cut -d . -f1
}
div 10 3

본 사례 테스트 인원 명단
# vim member.txt
xiaoguisheng
guoyuqing
xiongyongzheng
mengjintang
chaizuzhou
zhousheng
xufangming
zhaoliangyun
hanshiru
wangxianyi
zhangjipei
luxiuli
yangshugen
guoyongzhi
lijianguo
wuqiongchen
dinglin
yaoyashan
yinzijia
wangbencheng
liuxiuwen
chenzuqi
leyuguo
baozongyao
fenghao
sunxiaoquan
zhangyaxian
lijiuzhe
dulichun
lixi
shenpeiwen
zousilin
luoping
chaiyan
fandaozhang
huzixiang
jinzhen
zhujunfeng
liqianbiao
hangyanliang
luorenjian
loujianji
fujianzhou
gengyiwu
jinjigui
liuzhizhong
lisanyan
lisili
zhangyiyu
songguozhen
zhangxinghua
zhaozhiyong
huanghe
xiaojie
fanhongfei
wangguiwen
renshumin
songfuying
zhanghaibo
liguangqun
puaihua
yanzhihua
gaojixian
liulai
funing
chenruizhi
chendaxin
laishaoying
xujian
xiaozhekou
xuxiaping
jiangchunqing

본 사례 참조 스 크 립 트
#!/bin/bash
#       
#  :
#  :
#  :v1.0

#      
f=member.txt
#   
group_n=7
#    
member_n=`wc -l $f|awk '{print $1}'`

#              id
get_n()
{
    #      cksum 
    l=`echo $1|cksum|awk '{print $1}'`
    #       
    n1=$RANDOM
    #cksum       ,         ,                  
    n2=$[$n1+$l]
    g_id=$[$n2%$group_n]
    #      7,     0-6,     0,    7
    if [ $g_id -eq 0 ]
    then
        g_id=$group_n
    fi
    echo $g_id
}

for i in `seq 1 $group_n`
do
    #n_$i.txt     ,           
    #       ,       ,                  
    [ -f n_$i.txt ] && rm -f n_$i.txt
done


shuf $f|while read name
do
    #         id
    g=`get_n $name`
    #               
    echo $name >> n_$g.txt
done

#           
nu(){
    wc -l $1|awk '{print $1}'
}

#           
max(){
    ma=0
    for i in `seq 1 $group_n|shuf`
    do
        n=`nu n_$i.txt`
        if [ $n -gt $ma ]
        then
            ma=$n
       fi
    done
    echo $ma
}

#           
min(){
    mi=$member_n
    for i in `seq 1 $group_n|shuf`
    do
       n=`nu n_$i.txt`
       if [ $n -lt $mi ]
       then
           mi=$n
       fi
    done
    echo $mi
}

#        
div()
{
    n=`echo "scale=1;$1/$2"|bc`
    n1=`echo "scale=1;$n+0.5"|bc`
    echo $n1|cut -d. -f1
}

#       (     )
ava_n=$[$member_n/$group_n]
#       (    )
ava_n1=`div $member_n $group_n`

if [ $ava_n -eq $ava_n1 ]
then
    #       
    ini_min=1
    #  while       ,                     
    # while      ,                 
    while [ $ini_min -lt $ava_n1 ]
    do
        #        
        m1=`max`
        #        
        m2=`min`
        for i in `seq 1 $group_n|shuf`
        do
            n=`nu n_$i.txt`
            #             f1(     ,           )
            if [ $n -eq $m1 ]
            then
                f1=n_$i.txt
            #             f2(     ,           )
            elif [ $n -eq $m2 ]
            then
                f2=n_$i.txt
            fi
        done
        # f1       
        name=`tail -n1 $f1`
        #         f2 
        echo $name >> $f2
        # f1          
        sed -i "/$name/d" $f1
        #             ini_min
        ini_min=`min`
    done
else
    #       
    ini_max=$member_n
    while [ $ini_max -gt $ava_n1 ]
    do
        #        
        m1=`max`
        #        
        m2=`min`
        for i in `seq 1 $group_n|shuf`
        do
            n=`nu n_$i.txt`
            #             f1(     ,           )
            if [ $n -eq $m1 ]
            then
                f1=n_$i.txt
                #             f2(     ,           )
            elif [ $n -eq $m2 ]
            then
                f2=n_$i.txt
            fi
        done
        # f1       
        name=`tail -n1 $f1`
        #         f2 
        echo $name >> $f2
        # f1          
        sed -i "/$name/d" $f1
        #             ini_min
        ini_max=`max`
    done
fi

for i in `seq 1 $group_n`
do
    echo -e "\033[34m$i     :\033[0m"
    cat n_$i.txt
    #       
    rm -f n_$i.txt
    echo
done

좋은 웹페이지 즐겨찾기