linux shell设计——CD唱片管理程序

此程序是l《inux程序设计》书上的例子。这里只是一些详细的分析。

“`
menu_choice=””
current_cd=””
title_file=”title.cdb”
tracks_file=”tracks.cdb”
temp_file=/tmp/cdb.

traprmf$tempfileEXITmenuchoicecurrentcd,title.cdbCDcdcatnum(cdtitle)(cdtype)(cdac)tracks.cdbCD(cdtrack)(cdttitle)
标示脚本当前运行进程的PID号
trap ‘rm -f tempfileEXITCTRL+ZorCTRL+C退rmf 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信息。 100grep" searchstr” titlefile> temp_file是从title_file文件中查找有searchchstr代表的字符串的行,然后将这些行重定向到temp_file文件中。
if [ -z “ cdcatnum]listtrackstrackwclset (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 (wcl title_file)计算title_file文件里的行数,就是CD的个数
set (wcl 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 > tempfiletracksfilecdcatnumtempfilenumtracks= (wc -l tempfile)numtrackscutf2d, 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 赋值语句等号两边不能有空格

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值