此程序是l《inux程序设计》书上的例子。这里只是一些详细的分析。
“`
menu_choice=””
current_cd=””
title_file=”title.cdb”
tracks_file=”tracks.cdb”
temp_file=/tmp/cdb.
trap ‘rm -f tempfile′EXIT当按CTRL+ZorCTRL+C退出时执行rm−f temp_file,删除临时文件
get_confirm()
{
echo -e "Are you sure? \c"
while true
do
read x
case "$x" in
y|yes) return 0;;
n|no) echo
echo "cancelled"
return 1;;
*) echo "Please ecter yes or no";;
esac
done
}
get_confirm函数是为了方便用户确认的,输入y或yes返回0,n或no返回1 输入其它则提示提示语
set_menu_choice()
{
clear
echo "Options: -"
echo " a)Add new CD"
echo " f)Find CD"
echo " c)Count the CDs amd tracks int the catalog"
if [ "$cdcatnum" != "" ] ; then
echo "1) List"
echo "r) Remove $cdtitle"
echo "u) Update track infomation for $cdtitle"
fi
echo " q) quit"
echo
echo "Please enter choice then press return \c"
read menu_choice
return
}
set_menu_choice()函数是菜单选项,注意if语句[]括号里必须有两个空格相隔,当cdcatnum不为空时,弹出if判断语句中的提示,然后用户从键盘读入menu_choice(菜单选项)
insert_title()
{
echo $* >> $title_file
return
}
insert_track()
{
echo $* >> $tracks_file
return
}
inset_tittle()函数是将调用insert_tittle函数时传进来的参数一一拷贝到变量title_file代表的文件中,具体是CD目录编号,标题,曲目类型,作曲家。
inset_track()函数是将调用insert_track函数时传进来的参数一一拷贝到变量track_file代表的文件中,具体是目录编号,曲目编号,曲名。
在后面的设置中将环境变量IFS设置为”,“表明参数以”,“隔开,所以输入到文件中的信息也以”,“分隔。
add_record_tracks()
{
echo "Enter track"
echo "when n more tracks enter q"
cdtrack=1
cdttitle=""
while [ "$cdttitle" != "q" ]
do
echo -e "Track $cdtrack. track title? \c"
read tmp
cdttitle=${tmp%%,*}
echo cdttitle:$cdttitle tmp:$tmp
if [ "$tmp" != "$cdttitle" ]; then
echo "Sorry ,no commas alllowed"
continue
fi
if [ -n "$cdttitle" ] ; then
if [ "$cdttitle" != "q" ] ;then
echo arch : $cdcatnum $cdtrack $cdttitle
insert_track $cdcatnum,$cdtrack,$cdttitle
fi
else
cdtrack=$((cdtrack-1))
fi
cdtrack=$((cdtrack+1))
done
}
add_record_tracks()函数是往tracks.cdb添加曲目文件,cdttitle={tmp%%,*} 是一种参数扩展方法,将从tmp代表的字符串尾部开始删除“,*”匹配的最大部分,“,*”是以“,”开头的任意字符串,。为什么要删除以“,”开头的字符串 ,因为后面将IFS环境变量修改为‘,’了,所以则表示将参数用","隔开,如insert_trackcdcatnum, cdtrack, cdttitle,则用“,”隔开每个参数。if [ “ tmp"!=" cdttitle” ];是判断输入的tmp是否带有“.“字符串,如果有的话,则输入的字符串不符合要求。insert_track cdcatnum, cdtrack,$cdttitle,是将CD标题文件信息输入到track文件中。 而且如果输入的信息中带有”,“结尾的话就会从文件读取信息产生误判,因为文件读取是以”,“来分隔的。
add_records()
{
echo -e "Enter catalog name \c"
read tmp
cdcatnum=${tmp%%,*}
echo -e "Enter title \c"
read tmp
cdtittle=${tmp%%,*}
echo -e "Enter type \c"
read tmp
cdtype=${tmp%%,*}
echo -e "Enter artist/composer \c"
read tmp
cdac=${tmp%%,*}
echo About to add new entry
echo "$cdcatnum $cdtittle $cdtype $cdac"
if get_confirm ;then
insert_title $cdcatnum,$cdtittle,$cdtype,$cdac
add_record_tracks
else
remove_records
fi
return
}
add_records()是添加标题文件。同样也要判断输入要满足要求不能有”,*“。有两个选项,一个是将输入的信息添加到文件中,另一个是将输入的信息从文件中删除。删除是以cdcatnum问标示来删除的。具体怎么删除会在下面讲述。
find_cd()
{
if [ "$1" = "n" ] ;then
asklist=n
else
asklist=y
fi
cdcatnum=""
echo -e "Enter a string to search for in the CD titles \c"
read searchstr
if [ "$searchstr" = "" ];then
return 0
fi
grep "$searchstr" $title_file > $temp_file
set $(wc -l $temp_file)
linesfound=$1
case "$linesfound" in
0) echo "Sorry nothing found"
get_return
return 0
;;
1) ;;
2) echo "Sorry not unique."
echo "Found the following"
cat $temp_file
get_return
return 0
esac
IFS=","
read cdcatnum cdtitle cdtype cdac < $temp_file
IFS=" "
if [ -z "$cdcatnum" ];then
echo "Sorry,could not extract catalog field form $temp_file"
get_return
return 0
fi
echo
echo Catalog number: $cdcatnum
echo Title: $cdtitle
echo Type:$cdtype
echo Artist/Composer: $cdac
echo
get_return
if [ "$asklist" = "y" ];then
echo -e "View tracks for this CD? \c"
read x
if [ "$x"= "y" ];then
echo
list_tracks
echo
fi
fi
return 1
}
find_cd是用来查找CD信息。
1标示传入的第二个参数(参数是从0开始的,第0个参数是函数本身)。grep"
searchstr”
titlefile>
temp_file是从title_file文件中查找有searchchstr代表的字符串的行,然后将这些行重定向到temp_file文件中。
if [ -z “
cdcatnum”]表示当前字符串为空的话为真。listtracks就是根据输入的信息在track文件中来寻找相关信息。具体怎么寻找下面有详细介绍。wc命令为打印文件的行,单词,字符个数。−l选项为打印行数。set
(wc -l
tempfile)linesfound=
1就是从wc命令输出结果中提取第一个参数(行数)并赋值给linesfound变量。然后从temp_file文件中提取CD信息,并赋值给各个变量。如果temp文件中没有信息,说明没有找到相关信息,就输入提示。所以这个函数也可以寻找CD目录编号,并赋值到cdcatnum变量中,这个功能在下面的update_cd函数要用到。
update_cd()
{
if [ -z "$cdcatnum" ]; then
echo "You must select a CD first"
find_cd n
fi
if [ -n "$cdcarnum" ]; then
echo "Current tracks are :-"
list_tracks
echo
echo "This will re-enter the tracks for $cdtitle"
get_confirm && {
grep -v "^{cdcatnum}," $tracks_file > $temp_file
mv $temp_file $tracks_file
echo
add_record_tracks
}
fi
return
}
update_cd()是重新输入CD曲目文件的资料到track_file文件中。如果cdcatnum变量为空,则利用前面的find_cd函数来根据你的输入相关信息找到所属的CD目录编号。因为在title.cdb文件中每个CD值占一行。
然后根据CD目录编号列出在tracks.cdb文件中对应的曲目文件信息。
get_confirm返回true的话才能运行后面花括号里的东西
“^{cdcatnum},”表示以cdcatnum开头的行并且在cdcatnum后紧跟一个”,“号。
grep -v “^{cdcatnum},”
tracksfile>
temp_file 表示寻找不和上述规则不符合的行。然后将这些不符合的行重定向搭配temp_file文件里。mv
tempfile
tracks_file将temp_file mv为tracks文件。然后tracks_file文件就只包含除了要更新的CD的其他CD信息了。然后再用add_record_tracks输入要更新的CD信息。
count_cds() {
set $(wc -l $title_file)
num_titles=$1
set $(wc -l $tracks_file)
num_tracks=$1
echo found $num_titles CDs, with a total if $num_tracks tracks
get_return
return
}
count_cds用计算CD数量。
set
(wc−l
title_file)计算title_file文件里的行数,就是CD的个数
set
(wc−l
tracks_file)计算tracks_file文件里的行数,就是总共的歌曲数
remove_records() {
if [ -z "$cdcatnum" ]; then
echo you must select a CD first
find_cd n
fi
if [ -n "$cdcatnum" ]; then
echo "You are abount to delete $cdtitle"
get_confirm && {
grep -v "^${cdcatnum}," $title_file > $temp_file
mv $temp_file $title_file
grep -v "^${cdcatnum}," $tracks_file > $temp_file
mv $temp_file $tracks_file
cdcatnum=""
echo Entry removed
}
get_return
fi
return
}
若cdcatnum为空则调用find_cd 并传入参数n说明只是根据输入的相关信息找CD目录编号。
grep -v "^${cdcatnum}," $title_file > $temp_file
mv $temp_file $title_file
grep -v "^${cdcatnum}," $tracks_file > $temp_file
mv $temp_file $tracks_file
这四行就是剔除与输入CD相关的信息。
然后将cdcatnum赋值为空,就是防止下次进来后,再次删除同时也为了方便调用其他函数时产生参数错误。
list_tracks(){
if [ "$cdcatnum" = "" ]; then
echo no CD selected yet
return
else
grep "^${cdcatnum}," $tracks_file > $temp_file
num_tracks=$(wc -l $temp_file)
if [ "$num_tracks" = "0" ]; then
echo no tracks found for $cdtitle
else {
echo
echo "$cdtitle : -"
echo
cut -f 2- -d , $temp_file
echo
} | ${PAGER:-more}
fi
fi
get_return
return
}
grep “^ cdcatnum," tracks_file > tempfile在tracksfile文件里查找以cdcatnum开头并且紧跟”,“的行,然后将结果输入到tempfile文件里。numtracks= (wc -l tempfile)用于统计行数,并赋值给numtracks变量。cut−f2−−d, temp_file 从temp_file文件 以行为单位,以”,“为分隔符,来截取,并截取从第二段到最后一段。这样就将tracks_file文件里的CD目录编号去掉了。就只能输出曲目编号和曲名
rm -f $temp_file
if [ ! -f $title_file ]; then
touch $title_file
fi
if [ ! -f $tracks_file ]; then
touch $tracks_file
fi
clear
echo
echo
echo "Mini CD manger"
sleep 1
quit=n
while [ "$quit" != "y" ]
do
set_menu_choice a
case "$menu_choice" in
a) add_records;;
r) remove_records;;
f) find_cd y;;
u) update_cd;;
c) count_cds;;
l) list_tracks;;
b)
echo
more 4title_file
echo
get_return;;
q | Q) quit=y;;
*) echo "Sorry", choice not recognized ;;
esac
done
rm -f $temp_file
echo "Finished"
exit 0
这一段就相当于main函数了。quit=n 赋值语句等号两边不能有空格