사례 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