练习56
在文本文档1.txt第5行(假设文件行数大于5)后面增加如下内容:
This is a test file.
Test insert line into this file.
#!/bin/bash
n=0
cat 1.txt |while read line
do
n=$[$n+1]
if [ $n -eq 5 ]
then
echo $line
echo -e "# This is a test file.\n# Test insert line into this file."
else
echo $line
fi
done
练习57
设计一个shell程序,在每月第一天备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式"yymmdd_etc.tar.gz",yy为年,mm为月,dd为日。
#!/bin/bash
d1=date +%d
d2=date +%y%m%d
if [ $d1 == "01" ]
then
cd /etc/
tar czf /root/bak/$d2_etc.tar.gz ./
fi
练习58
将文件内所有的单词的重复次数计算出来,只需要列出重复次数最多的10个单词。
#!/bin/bash
for w in sed 's/[^a-zA-Z]/ /g' $1
do
echo $w
done |sort |uniq -c |sort -nr|head
练习59
需求是,把所有的成员平均分成若干个小组。这里,提供一个人员列表,比如成员有50人,需要分成7个小组,要求随机性,每次和每次分组的结果应该不一致。
#!/bin/bash
#人员列表文件
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
练习60
写一个shell脚本,比较两个数的大小,支持浮点数,两个数通过shell参数的形式提供。
#!/bin/bash
if [ $# -ne 2 ]
then
echo "请提供两个参数."
exit
fi
if_number()
{
if echo $1|grep -q '^-'
then
nu=echo $1|sed 's/^-//'
else
nu=$1
fi
n=echo $nu|sed 's/[0-9.]//g'
if [ -n "$n" ]
then
echo "$1不是合法数字."
exit
fi
if echo $1|grep -q '^.'
then
echo "$1不是合法数字."
exit
fi
}
if_number $1
if_number $2
n1=echo "$1>$2"|bc
if [ $n1 -eq 1 ]
then
echo "$1 > $2"
else
if [ "$1" == "$2" ]
then
echo "$1 = $2"
else
echo "$1 < $2"
fi
fi