第2章Shell编程没什么多说的,记录个代码,本章最后的那个简单的CD管理程序
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
#
!/
bin
/
sh
#Verysimpleexampleshellscript for managingaCDcollection.
#Copyright(C) 1996 - 99 WroxPress.
#Thisprogram is freesoftware;youcanredistributeitand / ormodifyit
#underthetermsoftheGNUGeneralPublicLicense as publishedbythe
#FreeSoftwareFoundation;eitherversion 2 oftheLicense,or(atyour
#option)anylaterversion.
#Thisprogram is distributed in thehopesthatitwillbeuseful,but
#WITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
#MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.SeetheGNUGeneral
#PublicLicense for moredetails.
#YoushouldhavereceivedacopyoftheGNUGeneralPublicLicensealong
#with this program; if not,writetotheFreeSoftwareFoundation,Inc.
# 675 MassAve,Cambridge,MA 02139 ,USA.
#Thefirstthingto do is toensurethatsome global variablesthatwe ' llbeusing
#throughoutthescriptare set up.We set thetitleandtrackfilesandatemporaryfile.
#WealsotrapCtrl - C,soourtemporaryfile is removed if theuserinterruptsthescript.
menu_choice = ""
current_cd = ""
title_file = " title.cdb "
tracks_file = " tracks.cdb "
temp_file =/ tmp / cdb.$$
trap ' rm-f$temp_file ' EXIT
#Nowwedefineourfunctions,sothatthescript,executingfromthetopline,canfind
#allthefunctiondefinitionsbeforeweattempttocallanyofthem for thefirsttime.
#Toavoidrewritingthesamecode in severalplaces,thefirsttwofunctionsaresimple
#utilities.
get_return(){
echo - e " Pressreturn/c "
readx
return 0
}
get_confirm(){
echo - e " Areyousure?/c "
while true
do
readx
case " $x " in
y | yes | Y | Yes | YES)
return 0 ;;
n | no | N | No | NO)
echo
echo " Cancelled "
return 1 ;;
* )echo " Pleaseenteryesorno " ;;
esac
done
}
#Here,wecometothemainmenufunction,set_menu_choice.
#Thecontentsofthemenuvarydynamically,withextraoptionsbeingadded if aCDentry
#hasbeenselected.Notethatecho - emaynotbeportabletosomeshells.
set_menu_choice(){
clear
echo " Options:- "
echo
echo " a)AddnewCD "
echo " f)FindCD "
echo " c)CounttheCDsandtracksinthecatalog "
if [ " $cdcatnum " != "" ];then
echo " l)Listtrackson$cdtitle "
echo " r)Remove$cdtitle "
echo " u)Updatetrackinformationfor$cdtitle "
fi
echo " q)Quit "
echo
echo - e " Pleaseenterchoicethenpressreturn/c "
readmenu_choice
return
}
#Twomorevery short functions,insert_titleandinsert_track for addingtothedatabasefiles.
#Thoughsomepeoplehateone - linerslikethese,theyhelpmakeotherfunctionsclearer
#Theyarefollowedbythelargeradd_record_trackfunctionthatusesthem.
#Thisfunctionusespatternmatchingtoensurenocommasareentered(sincewe ' reusingcommas
# as afieldseparator),andalsoarithmeticoperationstoincrementthecurrenttracknumber
# as tracksareentered.
insert_title(){
echo$ * >> $title_file
return
}
insert_track(){
echo$ * >> $tracks_file
return
}
add_record_tracks(){
echo " EntertrackinformationforthisCD "
echo " Whennomoretracksenterq "
cdtrack = 1
cdttitle = ""
while [ " $cdttitle " != " q " ]
do
echo - e " Track$cdtrack,tracktitle?/c "
readtmp
cdttitle = ${tmp %% , * }
if [ " $tmp " != " $cdttitle " ];then
echo " Sorry,nocommasallowed "
continue
fi
if [ - n " $cdttitle " ];then
if [ " $cdttitle " != " q " ];then
insert_track$cdcatnum,$cdtrack,$cdttitle
fi
else
cdtrack = $((cdtrack - 1 ))
fi
cdtrack = $((cdtrack + 1 ))
done
}
#Theadd_recordsfunctionallowsentryofthemainCDinformation for a new CD.
add_records(){
#Prompt for theinitialinformation
echo - e " Entercatalogname/c "
readtmp
cdcatnum = ${tmp %% , * }
echo - e " Entertitle/c "
readtmp
cdtitle = ${tmp %% , * }
echo - e " Entertype/c "
readtmp
cdtype = ${tmp %% , * }
echo - e " Enterartist/composer/c "
readtmp
cdac = ${tmp %% , * }
#Checkthattheywanttoentertheinformation
echoAbouttoadd new entry
echo " $cdcatnum$cdtitle$cdtype$cdac "
#Ifconfirmedthenappendittothetitlesfile
if get_confirm;then
insert_title$cdcatnum,$cdtitle,$cdtype,$cdac
add_record_tracks
else
remove_records
fi
return
}
#Thefind_cdfunctionsearches for thecatalognametext in theCDtitlefile, using the
#grepcommand.Weneedtoknowhowmanytimesthe string wasfound,butgreponlyreturns
#avaluetellingus if itmatchedzerotimesormany.To get around this ,westorethe
#output in afile,whichwillhaveonelinepermatch,thencountthelines in thefile.
#Thewordcountcommand,wc,haswhitespace in itsoutput,separatingthenumberoflines,
#wordsandcharacters in thefile.Weusethe$(wc - l$temp_file)notationtoextractthe
#firstparameterfromtheoutputto set thelinesfoundvariable.Ifwewantedanother,
#laterparameterwewouldusethe set commandto set theshell ' sparametervariablesto
#thecommandoutput.
#WechangetheIFS(InternalFieldSeparator)toa,(comma),sowecanseparatethe
#comma - delimitedfields.Analternativecommand is cut.
find_cd(){
if [ " $1 " = " n " ];then
asklist = n
else
asklist = y
fi
cdcatnum = ""
echo - e " EnterastringtosearchforintheCDtitles/c "
readsearchstr
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,nothingfound "
get_return
return 0
;;
1 );;
2 )echo " Sorry,notunique. "
echo " Foundthefollowing "
cat$temp_file
get_return
return 0
esac
IFS = " , "
readcdcatnumcdtitlecdtypecdac < $temp_file
IFS = " "
if [ - z " $cdcatnum " ];then
echo " Sorry,couldnotextractcatalogfieldfrom$temp_file "
get_return
return 0
fi
echo
echoCatalognumber:$cdcatnum
echoTitle:$cdtitle
echoType:$cdtype
echoArtist / Composer:$cdac
echo
get_return
if [ " $asklist " = " y " ];then
echo - e " ViewtracksforthisCD?/c "
readx
if [ " $x " = " y " ];then
echo
list_tracks
echo
fi
fi
return 1
}
#update_cdallowsustore - enterinformation for aCD.Noticethatwesearch(grep)
# for linesthatstart( ^ )withthe$cdcatnumfollowedbya,,andthatweneedtowrap
#theexpansionof$cdcatnum in {}sowecansearch for a,withnowhitespacebetween
#itandthecataloguenumber.Thisfunctionalsouses{}toenclosemultiplestatements
#tobeexecuted if get_confirmreturns true .
update_cd(){
if [ - z " $cdcatnum " ];then
echo " YoumustselectaCDfirst "
find_cdn
fi
if [ - n " $cdcatnum " ];then
echo " Currenttracksare:- "
list_tracks
echo
echo " Thiswillre-enterthetracksfor$cdtitle "
get_confirm && {
grep - v " ^${cdcatnum}, " $tracks_file > $temp_file
mv$temp_file$tracks_file
echo
add_record_tracks
}
fi
return
}
#count_cdsgivesusaquickcountofthecontentsofourdatabase.
count_cds(){
set $(wc - l$title_file)
num_titles = $ 1
set $(wc - l$tracks_file)
num_tracks = $ 1
echofound$num_titlesCDs,withatotalof$num_trackstracks
get_return
return
}
#remove_recordsstripsentriesfromthedatabasefiles, using grep - vtoremoveall
#matchingstrings.Noticewemustuseatemporaryfile.
#Ifwetriedto do this ,
#grep - v " ^$cdcatnum " > $title_file
#the$title_filewouldbe set toemptybythe > outputredirectionbeforethegrep
#hadchancetoexecute,sogrepwouldreadfromanemptyfile.
remove_records(){
if [ - z " $cdcatnum " ];then
echoYoumustselectaCDfirst
find_cdn
fi
if [ - n " $cdcatnum " ];then
echo " Youareabouttodelete$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 = ""
echoEntryremoved
}
get_return
fi
return
}
#List_tracksagainusesgreptoextractthelineswewant,cuttoaccessthefields
#wewantandthenmoretoprovideapaginatedoutput.Ifyouconsiderhowmanylines
#ofCcodeitwouldtaketore - implementthese 20 - oddlinesofcode,you ' llappreciate
#howpowerfulatooltheshellcanbe.
list_tracks(){
if [ " $cdcatnum " = "" ];then
echonoCDselectedyet
return
else
grep " ^${cdcatnum}, " $tracks_file > $temp_file
num_tracks = $(wc - l$temp_file)
if [ " $num_tracks " = " 0 " ];then
echonotracksfound for $cdtitle
else {
echo
echo " $cdtitle:- "
echo
cut - f 2 - - d,$temp_file
echo
} | ${PAGER: - more}
fi
fi
get_return
return
}
#Nowallthefunctionshavebeendefined,wecanenterthemainroutine.
#Thefirstfewlinessimply get thefilesintoaknownstate,thenwecallthemenu
#function,set_menu_choice,andactontheoutput.
#Whenquit is selected,wedeletethetemporaryfile,writeamessageandexit
#withasuccessfulcompletioncondition.
rm - f$temp_file
if [ ! - f$title_file];then
touch$title_file
fi
if [ ! - f$tracks_file];then
touch$tracks_file
fi
#Nowtheapplicationproper
clear
echo
echo
echo " MiniCDmanager "
sleep 1
quit = n
while [ " $quit " != " y " ];
do
set_menu_choice
case " $menu_choice " in
a)add_records;;
r)remove_records;;
f)find_cdy;;
u)update_cd;;
c)count_cds;;
l)list_tracks;;
b)
echo
more$title_file
echo
get_return;;
q | Q)quit = y;;
* )echo " Sorry,choicenotrecognized " ;;
esac
done
#Tidyupandleave
rm - f$temp_file
echo " Finished "
exit 0
#Verysimpleexampleshellscript for managingaCDcollection.
#Copyright(C) 1996 - 99 WroxPress.
#Thisprogram is freesoftware;youcanredistributeitand / ormodifyit
#underthetermsoftheGNUGeneralPublicLicense as publishedbythe
#FreeSoftwareFoundation;eitherversion 2 oftheLicense,or(atyour
#option)anylaterversion.
#Thisprogram is distributed in thehopesthatitwillbeuseful,but
#WITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
#MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.SeetheGNUGeneral
#PublicLicense for moredetails.
#YoushouldhavereceivedacopyoftheGNUGeneralPublicLicensealong
#with this program; if not,writetotheFreeSoftwareFoundation,Inc.
# 675 MassAve,Cambridge,MA 02139 ,USA.
#Thefirstthingto do is toensurethatsome global variablesthatwe ' llbeusing
#throughoutthescriptare set up.We set thetitleandtrackfilesandatemporaryfile.
#WealsotrapCtrl - C,soourtemporaryfile is removed if theuserinterruptsthescript.
menu_choice = ""
current_cd = ""
title_file = " title.cdb "
tracks_file = " tracks.cdb "
temp_file =/ tmp / cdb.$$
trap ' rm-f$temp_file ' EXIT
#Nowwedefineourfunctions,sothatthescript,executingfromthetopline,canfind
#allthefunctiondefinitionsbeforeweattempttocallanyofthem for thefirsttime.
#Toavoidrewritingthesamecode in severalplaces,thefirsttwofunctionsaresimple
#utilities.
get_return(){
echo - e " Pressreturn/c "
readx
return 0
}
get_confirm(){
echo - e " Areyousure?/c "
while true
do
readx
case " $x " in
y | yes | Y | Yes | YES)
return 0 ;;
n | no | N | No | NO)
echo
echo " Cancelled "
return 1 ;;
* )echo " Pleaseenteryesorno " ;;
esac
done
}
#Here,wecometothemainmenufunction,set_menu_choice.
#Thecontentsofthemenuvarydynamically,withextraoptionsbeingadded if aCDentry
#hasbeenselected.Notethatecho - emaynotbeportabletosomeshells.
set_menu_choice(){
clear
echo " Options:- "
echo
echo " a)AddnewCD "
echo " f)FindCD "
echo " c)CounttheCDsandtracksinthecatalog "
if [ " $cdcatnum " != "" ];then
echo " l)Listtrackson$cdtitle "
echo " r)Remove$cdtitle "
echo " u)Updatetrackinformationfor$cdtitle "
fi
echo " q)Quit "
echo
echo - e " Pleaseenterchoicethenpressreturn/c "
readmenu_choice
return
}
#Twomorevery short functions,insert_titleandinsert_track for addingtothedatabasefiles.
#Thoughsomepeoplehateone - linerslikethese,theyhelpmakeotherfunctionsclearer
#Theyarefollowedbythelargeradd_record_trackfunctionthatusesthem.
#Thisfunctionusespatternmatchingtoensurenocommasareentered(sincewe ' reusingcommas
# as afieldseparator),andalsoarithmeticoperationstoincrementthecurrenttracknumber
# as tracksareentered.
insert_title(){
echo$ * >> $title_file
return
}
insert_track(){
echo$ * >> $tracks_file
return
}
add_record_tracks(){
echo " EntertrackinformationforthisCD "
echo " Whennomoretracksenterq "
cdtrack = 1
cdttitle = ""
while [ " $cdttitle " != " q " ]
do
echo - e " Track$cdtrack,tracktitle?/c "
readtmp
cdttitle = ${tmp %% , * }
if [ " $tmp " != " $cdttitle " ];then
echo " Sorry,nocommasallowed "
continue
fi
if [ - n " $cdttitle " ];then
if [ " $cdttitle " != " q " ];then
insert_track$cdcatnum,$cdtrack,$cdttitle
fi
else
cdtrack = $((cdtrack - 1 ))
fi
cdtrack = $((cdtrack + 1 ))
done
}
#Theadd_recordsfunctionallowsentryofthemainCDinformation for a new CD.
add_records(){
#Prompt for theinitialinformation
echo - e " Entercatalogname/c "
readtmp
cdcatnum = ${tmp %% , * }
echo - e " Entertitle/c "
readtmp
cdtitle = ${tmp %% , * }
echo - e " Entertype/c "
readtmp
cdtype = ${tmp %% , * }
echo - e " Enterartist/composer/c "
readtmp
cdac = ${tmp %% , * }
#Checkthattheywanttoentertheinformation
echoAbouttoadd new entry
echo " $cdcatnum$cdtitle$cdtype$cdac "
#Ifconfirmedthenappendittothetitlesfile
if get_confirm;then
insert_title$cdcatnum,$cdtitle,$cdtype,$cdac
add_record_tracks
else
remove_records
fi
return
}
#Thefind_cdfunctionsearches for thecatalognametext in theCDtitlefile, using the
#grepcommand.Weneedtoknowhowmanytimesthe string wasfound,butgreponlyreturns
#avaluetellingus if itmatchedzerotimesormany.To get around this ,westorethe
#output in afile,whichwillhaveonelinepermatch,thencountthelines in thefile.
#Thewordcountcommand,wc,haswhitespace in itsoutput,separatingthenumberoflines,
#wordsandcharacters in thefile.Weusethe$(wc - l$temp_file)notationtoextractthe
#firstparameterfromtheoutputto set thelinesfoundvariable.Ifwewantedanother,
#laterparameterwewouldusethe set commandto set theshell ' sparametervariablesto
#thecommandoutput.
#WechangetheIFS(InternalFieldSeparator)toa,(comma),sowecanseparatethe
#comma - delimitedfields.Analternativecommand is cut.
find_cd(){
if [ " $1 " = " n " ];then
asklist = n
else
asklist = y
fi
cdcatnum = ""
echo - e " EnterastringtosearchforintheCDtitles/c "
readsearchstr
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,nothingfound "
get_return
return 0
;;
1 );;
2 )echo " Sorry,notunique. "
echo " Foundthefollowing "
cat$temp_file
get_return
return 0
esac
IFS = " , "
readcdcatnumcdtitlecdtypecdac < $temp_file
IFS = " "
if [ - z " $cdcatnum " ];then
echo " Sorry,couldnotextractcatalogfieldfrom$temp_file "
get_return
return 0
fi
echo
echoCatalognumber:$cdcatnum
echoTitle:$cdtitle
echoType:$cdtype
echoArtist / Composer:$cdac
echo
get_return
if [ " $asklist " = " y " ];then
echo - e " ViewtracksforthisCD?/c "
readx
if [ " $x " = " y " ];then
echo
list_tracks
echo
fi
fi
return 1
}
#update_cdallowsustore - enterinformation for aCD.Noticethatwesearch(grep)
# for linesthatstart( ^ )withthe$cdcatnumfollowedbya,,andthatweneedtowrap
#theexpansionof$cdcatnum in {}sowecansearch for a,withnowhitespacebetween
#itandthecataloguenumber.Thisfunctionalsouses{}toenclosemultiplestatements
#tobeexecuted if get_confirmreturns true .
update_cd(){
if [ - z " $cdcatnum " ];then
echo " YoumustselectaCDfirst "
find_cdn
fi
if [ - n " $cdcatnum " ];then
echo " Currenttracksare:- "
list_tracks
echo
echo " Thiswillre-enterthetracksfor$cdtitle "
get_confirm && {
grep - v " ^${cdcatnum}, " $tracks_file > $temp_file
mv$temp_file$tracks_file
echo
add_record_tracks
}
fi
return
}
#count_cdsgivesusaquickcountofthecontentsofourdatabase.
count_cds(){
set $(wc - l$title_file)
num_titles = $ 1
set $(wc - l$tracks_file)
num_tracks = $ 1
echofound$num_titlesCDs,withatotalof$num_trackstracks
get_return
return
}
#remove_recordsstripsentriesfromthedatabasefiles, using grep - vtoremoveall
#matchingstrings.Noticewemustuseatemporaryfile.
#Ifwetriedto do this ,
#grep - v " ^$cdcatnum " > $title_file
#the$title_filewouldbe set toemptybythe > outputredirectionbeforethegrep
#hadchancetoexecute,sogrepwouldreadfromanemptyfile.
remove_records(){
if [ - z " $cdcatnum " ];then
echoYoumustselectaCDfirst
find_cdn
fi
if [ - n " $cdcatnum " ];then
echo " Youareabouttodelete$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 = ""
echoEntryremoved
}
get_return
fi
return
}
#List_tracksagainusesgreptoextractthelineswewant,cuttoaccessthefields
#wewantandthenmoretoprovideapaginatedoutput.Ifyouconsiderhowmanylines
#ofCcodeitwouldtaketore - implementthese 20 - oddlinesofcode,you ' llappreciate
#howpowerfulatooltheshellcanbe.
list_tracks(){
if [ " $cdcatnum " = "" ];then
echonoCDselectedyet
return
else
grep " ^${cdcatnum}, " $tracks_file > $temp_file
num_tracks = $(wc - l$temp_file)
if [ " $num_tracks " = " 0 " ];then
echonotracksfound for $cdtitle
else {
echo
echo " $cdtitle:- "
echo
cut - f 2 - - d,$temp_file
echo
} | ${PAGER: - more}
fi
fi
get_return
return
}
#Nowallthefunctionshavebeendefined,wecanenterthemainroutine.
#Thefirstfewlinessimply get thefilesintoaknownstate,thenwecallthemenu
#function,set_menu_choice,andactontheoutput.
#Whenquit is selected,wedeletethetemporaryfile,writeamessageandexit
#withasuccessfulcompletioncondition.
rm - f$temp_file
if [ ! - f$title_file];then
touch$title_file
fi
if [ ! - f$tracks_file];then
touch$tracks_file
fi
#Nowtheapplicationproper
clear
echo
echo
echo " MiniCDmanager "
sleep 1
quit = n
while [ " $quit " != " y " ];
do
set_menu_choice
case " $menu_choice " in
a)add_records;;
r)remove_records;;
f)find_cdy;;
u)update_cd;;
c)count_cds;;
l)list_tracks;;
b)
echo
more$title_file
echo
get_return;;
q | Q)quit = y;;
* )echo " Sorry,choicenotrecognized " ;;
esac
done
#Tidyupandleave
rm - f$temp_file
echo " Finished "
exit 0