实验9:shell及shell编程
1、实验目的
1)sed的使用;
2)awk的应用;
3)shell及shell编程;
4) 与用户启动相关的文件及使用。
2、实现设备
一台装有Windows操作系统和Linux机系统的微机或服务器。
3、实验方法与注意事项
1)由于是以root用户工作的,权力很大,请不要在系统内做对系统或对其他用户不安全的事情。
2)要求每个同学登录后系统后,要在自己的家目录内容以自己(汉语拼音)名字,使用mkdir命令创建一个子目录。以后所有工作都要在自己的目录内进行。
3)认真编写实验报告
4、实验过程
1) sed命令的使用:
(1) 将ifile文件中的所有sysman替换成System Manager并输出到ofile
sed -e 's/sysman/System Manager/g'
(2) 显示ifile文件中的所有注释行
#sed -e '/^#/!d' < ifile #参见不执行某命令!function
#sed -e '/^[[:blank:]]*#/!d' < ifile #此比上例更有效
(3) 删除文件ifile中的空行,并将其它的内容输出到ofile:
方法
#sed '
/^$/d
/^[
'
#注:tab为tab键,pace>为空格键。
方法 方法也可写为:
sed '/^$/d;/^[
sed '/^$/d;/^[[:blank:]]*$/d'
sed '/^$/d;/^[[:space:]]*$/d'
(4)其它应用
显示文件的前10行: (实现head [-10] file的功能)
sed -n -e '1,10p' file
sed -e '10q' file
统计文件的行数:(实现wc –l功能)
sed -n -e '$=' file
显示文件的后10行:(实现tail -10 file功能,此为一个简单的shell脚本程序)
x=`sed -n -e '$=' t`; y=$(($x-10)); sed -n -e "$y,\$p" t
说明:如果脚本命令较多,也可将整个脚本内容写入文件(比如e_script)中,此时命令的执行可如下进行:
sed –f e_script < ifile > ofile
2) awk命令的使用
(1) 显示系统内root的进程,它们是什么,进程号是多少
ps -ef | awk '/root/{ print $1, $2, $8 }'
或
ps -ef | awk '/^[[:blank:]]*root/{ print $1, $2, $8 }'
(2) 显示系统所非root用户在干什么,他们是谁?
ps -ef | awk '!/root/{ print $1, $8 }'
或
ps -ef | awk '!/^[[:blank:]]*root/{ print $1, $8 }' #更精确
(3) 使用awk计算文件infile内数字的和。
awk '{ sum += $1 }; END { print sum }' ifile
注:假设infile内容为数字串,且每个数字串占一行。
(4) 显示系统内已经注册(创建)的所有用户(显示/etc/passwd内的所有用户)
awk -F: '{ print $1 }' /etc/passwd #-F:指定域分隔符为“:”
(5) 统计文本文件的总行数
awk 'END { print NR }' file
3)shell编程
(1) 设计一个程序,带一个(目录)参数。实现功能:(1)首先判断是否带有参数,若无则显示用法信息后,报错返回;(2)带首先判断该参数是不是目录。若是则列目录的内容,否则,提示用户不是目录,则显示警告信息后报错返回。
#!/bin/sh
if [ $# -ne 1 ] #check if have 1 parameter
then
echo "Usage: $0 dir" #Diaplay Usage
exit 1 #return 1
fi
if [ -d "$1" ] #if is a dir;then
ls $1/*; exit 0 #list the dir,and return 0
fi
echo "Warn: $1 is not a directory" #Warning message
exit 2 #return 2
注:输入时可不输入注释部分。设此程序名为myls,为其增加执行权后,运行方法为:
./myls #返回码为1
./myls dir #如果dir是个目录,则列其内容
./myls file #若file是文件或不存在则给出警告后返回2
(2) 用嵌套式if-fi语句实现(1):
#!/bin/sh
if [ $# -ne 1 ] #check if have 1 parameter
then
echo "Usage: $0 dir" #Diaplay Usage
exit 1 #return 1
elif [ -d "$1" ] #if is a dir
then
ls $1/*; exit 0 #list the dir,and return 0
else
echo "Warn: $1 is not a directory" #Warning message
exit 2 #return 2
fi
(3) 设计一个程序,从命令行接收数值参数,并计算这些参数的和。
x=0
for y in $*
do
x=`expr $x + $y`
done
echo "The Sum is: $x"
注:设程序名为myadd,增加执行权后,运行方法为:myadd 20 35 100 60
但是,本程序是有问题的,原因是它没有判断输入数据的合法性。下面是一个增加输入数据合法性检查的程序。
x=0
for y in $*
do
z=`echo $y | awk '/^[[:digit:]]*$/ { print $0 }'`
if [ -z $z ]; then
echo -e "Invalid command line parameter: $y\a"; exit 1
fi
x=`expr $x + $y`
done
echo "The Sum is: $x"
(4) 设计一个程序,计算前n个正整数的和:
x=0; y=1
while true
do
x=`expr $x + $y`
y=`expr $y + 1`
if [ $y -gt $1 ]; then break; fi
done
echo "1+2+..+$1=$x"
注:此程序要带有1个参数作为整数n,以计算前n个正整数的和。设程序名为myadd1,则运行方法是:myadd1 10或myadd1 100等。
(5)使用bsh编程,实现以下功能:从命令接收不定数量的命令行参数,参数为程序中要处理的文本文件名,程序要判断每个参数所表示的文件名是否存在,不存在时报错,若存在则显示其文本总行数。
#!/bin/sh
if [ $# -eq 0 ]; then echo "$0: no input file!"; exit 1; fi
while [ $# -gt 0 ]
do
if [ ! -e $1 ]; then echo "$1: dosn't exist!"; exit 1; fi
if [ -f $1 ]; then
echo -n "$1:";
#以下3句中的任何一个均可,或其它能够实现此功能语句亦可
sed -n -e '$=' $1;
awk 'END { print NR }' $1;
wc -l $1 | awk '{ print $1 }'
else echo -n "$1:i Not a text file"
fi
shift
done
(6)here文档
#!/bin/sh
cmd="uname -s"; name=`whoami`
cat << !
My name is $name, I am a student.
I study computer, and now I have an exam of `$cmd` OS.
!
4) 与用户登录相关文件
.bash_history #历史文件
.bash_logout #用户注销时要执行的文件
.bash_profile #用户登录时要执行的文件
.bashrc #用户登录时要执行的文件,由.bash_profile调用
/etc/bashrc #用户登录时要执行的文件,由.bashrc调用
/etc/profile #用户登录时要执行的文件,由/etc/bashrc调用
/etc/profile.d/* #用户登录时要执行的文件,由/etc/profile调用
用户可以根据需要修改,它们的内容。
以下为一个菜单程序(可取名为sh_add),可将它加在用户.bash_profile的最后,当用户登录时,若成功则直接执行此程序而进入菜单控制,当用户退出菜单时直接注销自己,回到login登录界面。
trap '' 1 2 3 15 #trap the signal 1,2,3,15
func1( ){
echo -e "\n\n\t\t\tThist is Function 2 Demontration!"
echo -e "\t\t\t1111111111111111111111111111111!"
}
func2( ){
echo -e "\n\n\t\t\tThist is Function 2 Demontration!"
echo -e "\t\t\t2222222222222222222222222222222!"
}
while true
do
clear
echo -en "
\t+-----------------------------------------------------+\n\
\t| |\n\
\t| 1.func1 2.func2 q.quit |\n\
\t| |\n\
\t+-----------------------------------------------------+\n\
\t\t\tPlease get Select 1,2 or q:"
read x
case $x in
1)
func1;;
2)
func2;;
s|S)
trap 1 2 3 15
break;;
Q|q)
exit 0;;
*)
echo -e "\a";;
esac
echo -en "\n\t\t\tPress Enter Key to Contiune:"
read x; clear
done
注意:应$HOME/.bash_profile的最后加入一行:
. sh_add
让该程序在当前shell内运行。
当此文件放在$HOME/.bash_profile内后,X-Windows将无法正常启动。注释掉此命令所在行后可恢复X-Windows正常启动。也可以通过在以上代码中的while true加入根据终端号进行判断办法来实现:具体做是当用户在/dev/tty1~/dev/tty12是使用本程序时执行while true语句段,否则跳过while true;do … done语句段,什么都不做。(由用户自己完成)
当然,用户也可以修改$HMOE/.bash_profile干别的事情,比如设置环境变量等。此方法在用户登录控制设置时是非常有用的。
请实验者关注程序中两个trap语句的作用。S|s的功能是什么?
4、实验报告的内容与书写
以书面形式记录下你的每一步过程,包括输入、输出信息,遇到的问题和解决的办法。