shell脚本练习题.docx
《shell脚本练习题.docx》由会员分享,可在线阅读,更多相关《shell脚本练习题.docx(26页珍藏版)》请在冰点文库上搜索。
shell脚本练习题
shell脚本例子集锦(习题总结)
练习一:
写一个脚本
1.设定变量FILE的值为/etc/passwd
2.依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么
形如:
(提示:
LINE='wc-l/etc/passwd|cut-d""-fl')Hello,root,yourUIDis0.
3.统计一个有多少个用户
答案一:
#!
/bin/bash
file="/etc/passwd"
LINES='wc-l$file|cut-d""-f1'
forIin'seq1$LINES';do
userid='head-$I$file|tail-1|cut-d:
-f3'
username='head-$I$file|tail-1|cut-d:
-f1'
echo"hello$username,yourUIDis$userid"
done
echo"thereare$LINESusers"
答案二:
#!
/bin/bash
file=/etc/passwd
letnum=0forIin'cat$file';dousername='echo"$I"|cut-d:
-f1'userid='echo"$I"|cut-d:
-f3'echo"Hello,$username,yourUIDis$userid"num=$[$num+1]doneecho"thereare$numusers"
练习二:
写一个脚本
1.切换工作目录至/var
2.依次向/var目录中的每个文件或子目录问好,形如:
(提示:
forFILEin/var/*;或forFILEin'ls/var';)Hello,log
3.统计/var目录下共有多个文件,并显示出来
答案:
#!
/bin/bash
cd/var
letnum=0
forIin'ls/var/*';doecho"hello$I"num=$[$num+1]
doneecho"thenumberoffilesis$num"练习三:
写一个脚本
1.设定变量file的值为/etc/passwd
2.使用循环读取文件/etc/passwd的第2,4,6,10,13,15行,并显示其内容
3.把这些行保存至/tmp/mypasswd文件中答案:
#!
/bin/bash
file="/etc/passwd"
forIin246101315;doexec3>/tmp/mypasswd
line='head-$1$file|tail-1'echo"$line"echo"$line">&3exec3>&-done
练习四:
写一个脚本
传递两个整数给脚本,让脚本分别计算并显示这两个整数的和,
差,积,商
答案如下:
vimtest.sh
#!
/bin/bash
输出第一个数)
echo"firstnumber$1"
(表示
输出第二个数)
echo"secondnumber$2"
echo"
(表示
$(($1+$2))"
(输出两数之和)
echo
"$[$1-$2]"
(输出两数之差)
echo
"$[$1*$2]"
(输出两数之积)
echo
"$[$1/$2]"
(输出两数之商)
:
wq
(表示保存并退出vi编辑器)
chmod+x
test.sh
(给test.sh执行的权限)
./test.sh2
3
(传递两个参数并执行脚本
作业一:
写一个脚本:
1.创建目录/tmp/scripts
2.切换工作目录至此目录中
3.复制/etc/pam.d目录至当前目录,并重命名为test
4.将当前目录的test及其里面的文件和子目录的属主改为
redhat
5.将test及其子目录中的文件的其它用户的权限改为没有任何权限
答案:
#!
/bin/bashmkdir-v/tmp/scriptscd/tmp/scriptscp-r/etc/pam.d./testchown-Rredhat./testchmod-Ro=---./test
作业二:
写一个脚本
1.显示当前系统日期和时间,而后创建目录/tmp/lstest
2.切换工作目录至/tmp/lstest
3.创建目录a1d,b56e,6test
4.创建空文件xy,x2y,732
5.列出当前目录下以a,x或者6开头的文件或目录
6.列出当前目录下以字母开头,后跟一个任意数字,而后跟任意长度字符的文件或目录
答案:
#!
/bin/bashdatemkdir-pv/tmp/lstest
cd/tmp/lstestmkdira1db56e6testtouchxyx2y732
ls[ax6]*
ls[[:
alpha:
]][[:
digit:
]]*
作业三:
写一个脚本添加10个用户user1到user10,但要求只有用户不存在的情况下才能添加
答案:
#!
/bin/bash
forIin'seq110';do
cut-d:
-f1/etc/passwd|grep"user$I"2>>/tmp/etc.err||useradduser$I
done
作业四:
写一个脚本通过ping命令测试192.168.0.151到192.168.0.254之间的所有主机是否在线
如果在线,就显示“ipisup”如果不在线,就显示“ipisdown”答案:
#!
/bin/bash
forIin'seq151254';do
ping-c1-w1192.168.0.$I&>/dev/null&&echo"192.168.0.$I
isup"||
echo"192.168.0.$Iisdown"done
例题:
shell1.sh
显示日期和时间。
#!
/bin/bash
echo“currenttimeis'date'”//date要加反弓丨号
shell2.sh显示文件名,并显示位置参数(执行时带一个参数)。
(①$0是一个特殊的变量,它的内容是当前这个shell程序的文件名;②$1是一个位置
参数,位置参数之间用空格分隔,shell取第一个位置参数替换程序文件中的$1,第二个替换$2,依次类推。
)
#!
/bin/bash
echo“theprogramnameis$0//$”0是一个特殊的变数
echo“thefirstparais$1//$1是一个位置参数
echo“theprogramexit”//执行时带一个参数如./shell2.shabcd
shell3.sh判断并显示位置参数
#!
/bin/bash
if[-dechoelseecho
“$1”];then
“$1isdirectory,existed”
“$1doesnotexist,nowcreateit”
mkdir$1echo“$1iscreated
fi//执行时带一个参数
shell4.sh问候用户
#!
/bin/bashuser='whoami'case$userin
teacher)
echo“helloteacher”;;
root)
echo“helloroot”;;
*)
echo“hello$user,welcome”esac
1、求1+2+3+...+100的和是?
#!
/bin/bash
SUM=0
I=0
while[$I-le100]do
SUM=$((SUM+I))
I=$((I+1))
done
echo"由1+2+3+...+100的和是:
$SUM"
2、(基训十一)在根目录下有四个文件m1.txt,m2.txt,m3.txt,m4.txt,
用Shell编程,实现自动创建m1,m2,m3,m4四个目录,并将
ml.txt,m2・txt,m3・txt,m4・txt四个文件分别拷贝到各自相应的目录下。
#!
/bin/bash
cd/
touchm1・txtm2・txtm3・txtm4・txt
I=1
while[$I-le4]
do
mkdirm$I
cpm$I・txtm$I
I=$((I+1))done
3、(基训十二)编写一个名为myfirstshell.sh勺脚本,它包括以下内容
a)包含一段注释,列出您的姓名、脚本的名称和编写这个脚本的目的。
b)问候用户。
c)显示日期和时间。
d)显示这个月的日历。
e)显示您的机器名。
f)显示当前这个操作系统的名称和版本。
g)显示父目录中的所有文件的列表。
h)显示root正在运行的所有进程。
i)显示变量TERM、PATH和HOME的值。
j)显示磁盘使用情况。
k)用id命令打印出您的组ID。
m)跟用户说“Goodbye”
#!
/bin/bash
#09嵌入5号贾德进myfirstshell.shshe的简单编程user='whoami'
case$userin
root)
echo"helloroot";;
teacher)
echo"helloteacher";;
*)
echo"hello$user,welcome"
esac
echo"日期和时间:
'date'"
echo•本月的日历:
'cal'"
echo"本机的机器名:
'uname-n'"
echo"当前这个操作系统的名称和版本:
'uname-s;uname-r'"
echo"父目录中的所有文件的列表:
'ls../'"
echo"root正在运行的所有进程:
'ps-uroot'echo'变数TERM的值:
$TERM"
echo'变数PATH的值:
$PATH"
echo'变数HOME的值:
$HOME"
echo"磁盘的使用情况:
'df'"
echo"用id命令打印出你的组ID:
'id-g'"
echo"Goodbye!
"
4、(基训十三)设计一个Shell程序,在/userdata目录下建立50个目
录,即user1~user50,并设置每个目录的权限为rwxr-xr—
#!
/bin/bash
cd/userdata
I=1while[$I-le50]do
mkdir-puserdata/user$Ichmodo-xuser$II=$((I+1))done
5、(基训十四)编写shell程序,实现自动删除50个用户账号的功能账号名为stud1至stud50。
#!
/bin/bashcd/userdata
I=1
while[$I-le50]
do
mkdir-puserdata/user$Ichmodo-xuser$II=$((I+1))done6、(基训十四)设计一个shell程序,备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式yymmdd_etcyy为年,mm为月,dd为日。
#!
/bin/bash
DIRNAME='ls|root|grepbak'
if[-z$DIRNAME];then
mkdir/root/bak
cd/root/bak
fi
YY='date+%y'
MM='date+%m'
DD='date+%d'tarczvf${YY}${MM}${DD}_etc.gz/etcecho"etcbakfinshied"
7、(基训十四)某系统管理员需每天做一定的重复工作,请按照下列要求,编制一个解决方案:
(1)在下午4:
50删除/abc目录下的全部子目录和全部文件;
(2)下午5:
50将/data目录下的所有目录和文件归档并压缩为文件:
backup.tar.g;z
(3)在下午5:
55将IDE接口的第二个逻辑分区卸载。
//采用:
vipram.cron
#
(1)在下午4:
50删除/abc目录下的全部子目录和全部文件;
5016***rm-rf/abc/*
#
(2)下午5:
50将/data目录下的所有目录和文件归档并压缩为文件:
backup.tar.gz;
5017***tarczvfback.tar.gz/data
#(3)在下午5:
55将IDE接口的第二个逻辑分区卸载.
5517***umount/dev/hda6
//执行:
crontabpram.cron
设计一个Shell程序,在/userdata目录下建立50个目录,即userl〜user50,并设置每个目录的权限,其中其他用户的权限为:
读;文件所有者的权限为:
读、写、执行;文件所有者所在组的权限为:
读、执行。
程序实现及注释如下:
#!
/bin/bash
#adddir.sh
i=1
#while循环
while[$i-le50]
do
#利用test命令[-d/userdata]:
判断/userdata是否存在,如果存在直接创建子目录,不#
存在先创建/userdata再创建子目录。
if[-d/userdata]
then
#mkdir-p的意思是:
无论父目录/userdata存在与否,都会创建/userdata/user$i
mkdir-p/userdata/user$i
else
mkdir/userdata
mkdir-p/userdata/user$i
fi
#根据题目的意思:
/userdata/user$i应该是具有754权限,所以利用chmod赋权限。
chmod754/userdata/user$ii=$(($i+1))
done
函数in_path:
判断传入文件是否可执行,若可执行(且存在)返回0,否则返回1;
分析:
为测试传入文件是否在PATH所有的目录中,需取得PATH中的每个路径,可用循环,
但需要设定环境中的分隔符(借助环境变量IFS为PATH中的分隔符冒号”:
”
注:
$IFS输入分隔符.当shell读取输入数据的时候,会把一组字符看做是单词之间的分隔字符,它们通常
是空格,制表符,和换行符.
函数调用方式为:
in_pathfilename
in_path()
{
为函数的参数1,以此类推
#定义返回值变量
#设置新的IFS,并保存原来的以恢复使用
循环结构二:
for-in
条件语句之同行表示以分号隔开
判断文件有是否有可执行权限
cmd=$1#$1
retval=1
oldlFS=$IFSIFS=:
fordirectoryin$PATH#for
do
if[-xdirectory/$cmd];then#if
retval=0#-x
done
done
恢复原来IFS,
IFS=$oldIFS#
returnretval}
注:
1.函数的结构,没有形参
2.变量的引用需要符号$,而变量的定义或赋值则不需要。
3.赋值要无间隙,条件要间隙改进:
1.将路径、分隔符均作为函数的参数传入,应用得到扩展。
补充,in_path函数不能对绝对路径的文件处理,需写个函数对这一情况单独处理
checkForCmdInPath()
{
var=$1
#首先判断传入的非空串是否为绝对路径,即检测第一个字符是不是”/”,如果是,直接测-<
if[$var!
=“”];then#条件等价于-n$var
if[“${var%${var#?
}}”=‘/'];then#等价于$(echo$var|cut-c1)
if[!
-x$var];then
return1#notfoundornotexecutable
fi
elif!
inpath$var;then
return2#notfoundinPATH
fi
fi
}
注:
此函数让人一头雾水,详解如下:
1)表达式${var%${var#?
}}作匹配用,分解为${var%expr}${var#expr},expr为正则表达
式(?
匹配单一字符)
后者(带#的)返回expr与var匹配成功位置之后的所有内容,此处为var中第一字符之后的所有。
前者(带%的)返回expr与var匹配成功位置之前的所有内容,此处应为var的第一个字符。
等价于$(echo$var|cutc1)即取第一字符。
等价于${var:
beginpos:
size}中beginpos=0,size=1时的结果。
var的符号放在外面了,假设$var为$1,则表达式表示为${1%${1#?
}}
2)关于if的条件判断与C语言中的理解不一致,反映在上述的elif语句中的条件。
理解如下:
shell中的if条件可以是表达式(需加方括号[]),另外还可以是命令或函数(不需方括号),当命令执行成功时会后继执行具体操作,经测试,C语言中所说的true在shell中用0表示,即if0,才执行then,因为linux下的程序实现都是当返回0时表执行成功。
3)若函数中没有返回值,则它默认返回0,表执行成功。
函数的编写若遵从以上的原则,则对条件的理解依旧像C语言中的TRUE,FALSE—样理解
==============完善程序代码=====================================
#!
/bin/bash
in_path()
...#函数实现区域处理不路径返回0表找到、可执行,否则返回1
###############################
checkForCmdInPath()
返回1表没找到或不可执行,返回2
...#函数实现区域处理带路径和不带路径的
表没找到。
默认0表找到
################################
#####代码执行起始位置##############
if[$#-nq1];then
echo“Usage:
$0comman”d#$0
此文件时的输入串为准)
exit0
fi#调用函数,并经第一个参数传给函数checkForCmdInpath$1#对函数返回的结果进行判断$?
为函数的返回值,
表此执行文件(具体内容以执行
#case控制结构的
case$?
in格式,注意红色部分
2.写一个脚本,检测用户输入串的合法性,要求串由大小写字母、数字组成,无标点、特殊符号、空格。
思路:
将输入的串中非字母数字的内容删除或替换为空后若和原来输入的相同则合法,否则不合法。
isvalidAlphaNum()
{
compressed=”$(echo$1|sed's/卜[:
alnum:
]]//g')”#替换不合要求字符为空
if[“$compressed”!
=“$1”];then
return1#notvalide
else
return0#valide
fi
}
注:
1.关于引用变量时是否需要双引号的说明如果只是输出,可以不用双引号如果变量值代的内容中无空格,表达,特殊符号,在引用时可以不需要双引号,反之,最好带双引号,否则在变量处理时很有可
能会出现“参数过多”等莫名其妙的错误信息。
2.关于匹配处理,sed是单行编辑程序。
sed‘s/str1/str2/g'file将文件file中每
行内str1替换为str2
[[:
alnum:
]]表示所有字母和数字中的任一个字符。
若只是[:
alnum:
]则表示方括号中的任一
个字符。
F[:
alnum:
]]表除了所有字母数字外的任一字符。
如果是直接向脚本传字符串,则带空格的字串会被脚本自行分解为多个参数,所以可采用从标准输入读取的方式获得字串。
==============完善程序代码=====================================
#!
/bin/bash
isvalidAlphaNum()
...#函数体,判断字串的合法性
echo-n“Enterinput:
”#-n强制不换行
readinput#读取内容存到input中,无$符号
if!
isvalidAlphaNum“&input”;then#加引号,否则可能会出错。
echo“invalide”exit1
else
echo“valide”
fi
exit0
3.输入一个“monthdayyear”格式的日期串,程序将处理”month”为其英文单词
的前三个字母,第一个字母大写,其余的小写。
思路:
首先判断month是数字、还是单词,若是数字,则可查“数字—month”映射表(自定义case结构);若是单词,则取前三个字母,并格式化。
函数monthnoToName()将month数字转换为month名monthnoToName()
{
case$1in
1)month="Jan";;2)month="Feb";;
3)month="Mar";;4)month="Apr";;
5)month="May";;6)month="Jun";;
7)month="Jul";;8)month="Aug";;
9)month="Sep";;10)month="Oct";;
11)month="Nov";;12)month="Dec";;
*)echo"$0:
Unknownnumericmonthvalue$1">&2;exit1#
default,
esac#
return0
}
假设通过传三个参数到脚本——monthdayy