一个简单的CD唱片管理程序

    程序的原型来自于经典的<<Linux程序设计(第3版)>>,有用Shell编程实现的版本,有用C编程实现的版本。用C编程有多种方式,有用curses库实现的,有用ndbm数据库实现的,有用MySQL数据库实现的,后来还加了简单的图形界面(GTK+或Qt编写的)。程序都比较长,用到大量的库函数和系统调用。因此,这里我重点剖析了一下用Shell编程实现的版本,并做了一点小小的修改。Shell编程实现的程序最简单,也易于理解,分析起来方便。同样的功能用C来实现时可能需要大量的代码和一大堆的库函数调用,特别在涉及到输入输出的重定向时,由于Shell可以结合很多命令并用管道重定向,因此代码可能只需几行就可以了。

    程序如下(看不清的话可以让浏览器增大字符的显示):

#! /bin/bash # CD唱片应用程序,所有的函数原型如下: # get_return(): 获取返回字符(回车,在Linux中为换行符'/n') # get_confirm(): 获取确认字符(y,yes或n,no等) # set_menu_choice(): 显示菜单 # insert_title(): 插入唱片信息 # insert_track(): 插入曲目信息 # add_record_tracks(): 添加曲目记录(可一次添加多个曲目) # add_records(): 添加或唱片记录(根据确认也可以执行删除操作) # find_cd(): 查找并显示唱片信息 # update_cd(): 更新唱片的所有曲目 # count_cds(): 统计唱片数目和曲目总数 # remove_records(): 从数据库中删除唱片 # list_tracks(): 列出指定唱片的所有曲目 menu_choice="" # 当前选中的菜单项 current_cd="" # 用户当前选中的唱片 title_file="title.cdb" # 唱片信息的数据库文件 tracks_file="tracks.cdb" # 曲目信息的数据库文件 temp_file=/tmp/cdb.$$ # 临时文件 trap "rm -f $temp_file" EXIT # 对Ctrl+C的中断处理 # 工具型函数:获取返回字符 get_return(){ echo -e "Press return /c" read x return 0 } # 工具型函数:获取确认字符 get_confirm(){ echo -e "Are you sure? /c" while true; do read x case "$x" in y | yes | Y | Yes | YES ) return 0;; n | no | N | No | NO ) echo echo "Cancelled" return 1;; *) echo "Please enter yes or no";; esac done } # 主菜单函数:当用户选中某张CD唱片后,主菜单会多出几个选项 set_menu_choice(){ clear echo "Options :-" echo echo " a) Add new CD" echo " f) Find CD" echo " c) Count the CDs and tracks in the catalog" if [ "$cdcatnum" != "" ]; then # 当前唱片编号不为空,即用户选中了某张CD echo " 1) List tracks on $cdtitle" echo " r) Remove $cdtitle" echo " u) Update track information for $cdtitle" fi echo " q) Quit" echo echo -e "Please enter choice then press return /c" read menu_choice # 选择菜单项,并按回车 return } # 插入唱片信息 insert_title(){ echo $* >> $title_file return } # 插入曲目信息 insert_track(){ echo $* >> $tracks_file return } # 添加曲目记录:可一次添加多个曲目 add_record_tracks(){ echo "Enter track information for this CD" echo "When no more tracks enter q" # 有多个曲目时用q表示结束 cdtrack=1 # 当前曲目的编号 cdttitle="" while [ "$cdttitle" != "q" ]; do echo -e "Track $cdtrack, track title? /c" read tmp # 读入曲目的名称 cdttitle=${tmp%%,*} # 不能有逗号:截掉逗号及后面部分 if [ "$tmp" != "$cdttitle" ]; then echo "Sorry, no commas allowed" continue fi if [ -n "$cdttitle" ]; then # 若曲目名称不空且不是结束符q if [ "$cdttitle" != "q" ]; then insert_track $cdcatnum,$cdtrack,$cdttitle # 插入曲目记录:唱片目录编号、曲目编号、曲目名 fi else # 否则曲目名称为空,编号不变(这里先减1,后面还会加1) cdtrack=$((cdtrack-1)) fi cdtrack=$((cdtrack+1)) # 编号加1 done } # 添加或唱片记录(根据确认也可以执行删除操作) add_records(){ echo -e "Enter catalog number /c" read tmp # 读入唱片的类别编号 cdcatnum=${tmp%%,*} # 不能有逗号 echo -e "Enter title /c" read tmp # 读入唱片标题 cdtitle=${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 $cdtitle $cdtype $cdac" if get_confirm; then # 若确认为插入(y,yes),则插入唱片记录 insert_title $cdcatnu,$cdtitle,$cdtype,$cdac add_record_tracks # 在该唱片中插入曲目 else remove_records # 否则确认为删除(n,no),则删除唱片信息 fi return } # 查找并显示唱片信息 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 # 从数据库查找指定标题的唱片信息,放到temp_file文件中 set $(wc -1 $temp_file) # 统计唱片数量,wc统计文件的行数、单词数、字符数,输出的第1列就是行数信息 linefound=$1 case "$linefound" 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 from $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 } # 更新唱片的所有曲目 update_cd(){ if [ -z "$cdcatnum" ]; then echo "You must select a CD first" find_cd n fi if [ -n "$cdcatnum" ]; then echo "Current tracks are :-" list_tracks echo echo "This will re-enter the tracks for $cdtitle" get_confirm && { # 语句块,当get_confirm返回true时才会执行 grep -v "^${cdcatnum}," $tracks_file > $temp_file # 删除该唱片下的所有曲目 mv $temp_file $tracks_file echo add_record_tracks # 输入新的曲目 } fi return } # 统计唱片数目和曲目总数 count_cds(){ set $(wc -1 $title_file) num_titles=$1 set $(wc -1 $tracks_file) num_tracks=$1 echo "found $num_titles CDs, with a total of $num_tracks tracks" get_return return } # 从数据库中删除唱片 remove_records(){ if [ -z "$cdcatnum" ]; then echo "You must select a CD first" find_cd n fi if [ -n "$cdcatnum" ]; then echo "You are about to delete $cdtitle" get_confirm && { # 语句块:当get_confirm返回true时才会执行 # grep -v表示输出与正则表达式不匹配的行 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 } # 列出指定唱片的所有曲目 list_tracks(){ if [ "$cdcatnum" = "" ]; then echo "no CD selected yet" return else grep "^${cdcatnum}," $tracks_file > $temp_file num_tracks=$(wc -1 $temp_file) # 统计指定唱片有多少曲目 if [ "$num_tracks" = "0" ]; then echo "no tracks found for $cdtitle" else { # 把整个语句块的输出用管道重定向到more命令 echo echo "$cdtitle :-" echo cut -f2- -d, $temp_file # 列出每一行从第2个域(指定逗号为分隔符)开始的部分 echo } | ${PAGER:-more} # 通过more命令按页输出 fi fi get_return return } # 主程序 rm -f $temp_file if [ ! -f $title_file ]; then touch $title_file # 唱片数据库文件 fi if [ ! -f $tracks_file ]; then touch $title_file # 曲目数据库文件 fi clear echo echo echo "Mini CD manager" sleep 1 quit=n while [ "$quit" != "y" ]; do set_menu_choice # 调用主菜单函数,根据输出作相应操作 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 $title_file echo get_return;; q | Q) quit=y;; *) echo "Sorry, choice not recognize";; esac done rm -f $temp_file echo "Finished" exit 0

你可能感兴趣的:(编程,数据库,list,File,insert,menu)