一个简单的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

转载于:https://my.oschina.net/abcijkxyz/blog/723202

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值