【CD唱片shell脚本实现】实现方法
2013-12-23 10:02
537 查看
程序首先会执行菜单选择程序,然后根据用户输入的命令,再去执行相应的函数。
# Here, we come to the main menu function, set_menu_choice.
# The contents of the menu vary dynamically, with extra options being added if a CD entry
# has been selected. Note that echo -e may not be portable to some shells.
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
echo " l) 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
}
# Now the application proper
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 recognized";;
esac
done
# Tidy up and leave
rm -f $temp_file
echo "Finished"
exit 0
几个重要函数的实现
1、count_cds函数
在标题文件和曲目文件中,每一项以一行存储,所以只要统计有多少行数就可以了。程序通过命令:
set $(wc -l $title_file)
num_titles=$1
实现。
2、 find_cd函数
find函数需要一个参数,如果这个参数是y,他会在你输入主键找到一个CD唱片后询问你是否要查看这张CD的曲目。不过这个参数是固定配置的,方便程序员修改程序吧,用户不能自己配置。
程序中用到了环境变量IFS,这里介绍一下。
IFS(Internal Field Separator),是内部字段分隔符。
例:
它会把IFS中设置的字符替换为空格(分隔符)。
CD成片程序中是这样用的:
IFS=","
read cdcatnum cdtitle cdtype cdac < $temp_file
IFS=" "
temp_file文件中是以“,”号分割的字符串。
3、 list_tracks函数
# 搜索含变量cdcatnum的内容到temp_file,^代表指向一行的开头。
grep "^${cdcatnum}," $tracks_file > $temp_file
if [ "$num_tracks" = "0" ]; then
echo no tracks found for $cdtitle
else {
echo
echo "$cdtitle :-"
echo
# 用","分隔符分割temp_file中的字符串,并输出从第二段开始后面的
cut -f 2- -d , $temp_file
echo
# 如果PAGER没有定义或者为空,则返回more,否则返回PAGER。 # PAGER这个变量包含了浏览文件内容的程序的路径(例如less或者more)。
} | ${PAGER:-more}
fi
4、add_record_tracks函数
while [ "$cdttitle" != "q" ]
if [ -n "$cdttitle" ] ; then
这个函数里用的最多的是字符串的匹配,要注意的是"["的右,"]"的左,"="的左右都要留空格。
以下是整数,字符串以及文件操作的匹配符:
5、shell脚本的默认变量
$# 传入脚本的命令行参数个数
$* 所有命令行参数值,在各个参数值之间留有空格(作为单个字符串)
$0 命令本身(shell文件名)
$1 第一个命令行参数
${10} 第10个命令行参数
$? 返回值
$$ 脚本的进程ID
$@ 所有位置参数(每个作为独立的字符串)
CD唱片的shell实现的源码(程序源码来自《linux程序设计(第四版)》一书)
# Here, we come to the main menu function, set_menu_choice.
# The contents of the menu vary dynamically, with extra options being added if a CD entry
# has been selected. Note that echo -e may not be portable to some shells.
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
echo " l) 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
}
# Now the application proper
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 recognized";;
esac
done
# Tidy up and leave
rm -f $temp_file
echo "Finished"
exit 0
几个重要函数的实现
1、count_cds函数
在标题文件和曲目文件中,每一项以一行存储,所以只要统计有多少行数就可以了。程序通过命令:
set $(wc -l $title_file)
num_titles=$1
实现。
2、 find_cd函数
find函数需要一个参数,如果这个参数是y,他会在你输入主键找到一个CD唱片后询问你是否要查看这张CD的曲目。不过这个参数是固定配置的,方便程序员修改程序吧,用户不能自己配置。
程序中用到了环境变量IFS,这里介绍一下。
IFS(Internal Field Separator),是内部字段分隔符。
例:
它会把IFS中设置的字符替换为空格(分隔符)。
CD成片程序中是这样用的:
IFS=","
read cdcatnum cdtitle cdtype cdac < $temp_file
IFS=" "
temp_file文件中是以“,”号分割的字符串。
3、 list_tracks函数
# 搜索含变量cdcatnum的内容到temp_file,^代表指向一行的开头。
grep "^${cdcatnum}," $tracks_file > $temp_file
if [ "$num_tracks" = "0" ]; then
echo no tracks found for $cdtitle
else {
echo
echo "$cdtitle :-"
echo
# 用","分隔符分割temp_file中的字符串,并输出从第二段开始后面的
cut -f 2- -d , $temp_file
echo
# 如果PAGER没有定义或者为空,则返回more,否则返回PAGER。 # PAGER这个变量包含了浏览文件内容的程序的路径(例如less或者more)。
} | ${PAGER:-more}
fi
4、add_record_tracks函数
while [ "$cdttitle" != "q" ]
if [ -n "$cdttitle" ] ; then
这个函数里用的最多的是字符串的匹配,要注意的是"["的右,"]"的左,"="的左右都要留空格。
以下是整数,字符串以及文件操作的匹配符:
比较操作 | 整数操作 | 字符串操作 |
相同 | -eq | =或== |
不同 | -ne | != |
小于 | -lt | \< (ASCII) |
小于等于 | -le | |
大于 | -gt | \> (ASCII) |
大于等于 | -ge | |
-z (字符串为空) | ||
-n (字符串不为空) |
文件操作符 | -e | -f | -s | -d | -r | -w | -x |
说明 | 文件已经存在 | 文件是普通文件 | 文件大小不为零 | 文件是一个目录 | 文件对当前用户可以读取 | 文件对当前用户可以写入 | 文件对当前用户可以执行 |
$# 传入脚本的命令行参数个数
$* 所有命令行参数值,在各个参数值之间留有空格(作为单个字符串)
$0 命令本身(shell文件名)
$1 第一个命令行参数
${10} 第10个命令行参数
$? 返回值
$$ 脚本的进程ID
$@ 所有位置参数(每个作为独立的字符串)
CD唱片的shell实现的源码(程序源码来自《linux程序设计(第四版)》一书)
1 #!/bin/bash 2 3 # Very simple example shell script for managing a CD collection. 4 # Copyright (C) 1996-2007 Wiley Publishing Inc. 5 6 # This program is free software; you can redistribute it and/or modify it 7 # under the terms of the GNU General Public License as published by the 8 # Free Software Foundation; either version 2 of the License, or (at your 9 # option) any later version. 10 11 # This program is distributed in the hopes that it will be useful, but 12 # WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 # Public License for more details. 15 16 # You should have received a copy of the GNU General Public License along 17 # with this program; if not, write to the Free Software Foundation, Inc. 18 # 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 # The first thing to do is to ensure that some global variables that we'll be using 21 # throughout the script are set up. We set the title and track files and a temporary file. 22 # We also trap Ctrl-C, so our temporary file is removed if the user interrupts the script. 23 24 menu_choice="" 25 current_cd="" 26 title_file="title.cdb" 27 tracks_file="tracks.cdb" 28 temp_file=/tmp/cdb.$$ 29 trap 'rm -f $temp_file' EXIT 30 31 # Now we define our functions, so that the script, executing from the top line, can find 32 # all the function definitions before we attempt to call any of them for the first time. 33 # To avoid rewriting the same code in several places, the first two functions are simple 34 # utilities. 35 36 get_return() { 37 echo -e "Press return \c" 38 read x 39 return 0 40 } 41 42 get_confirm() { 43 echo -e "Are you sure? \c" 44 while true 45 do 46 read x 47 case "$x" in 48 y | yes | Y | Yes | YES ) 49 return 0;; 50 n | no | N | No | NO ) 51 echo 52 echo "Cancelled" 53 return 1;; 54 *) echo "Please enter yes or no" ;; 55 esac 56 done 57 } 58 59 # Here, we come to the main menu function, set_menu_choice. 60 # The contents of the menu vary dynamically, with extra options being added if a CD entry 61 # has been selected. Note that echo -e may not be portable to some shells. 62 63 set_menu_choice() { 64 clear 65 echo "Options :-" 66 echo 67 echo " a) Add new CD" 68 echo " f) Find CD" 69 echo " c) Count the CDs and tracks in the catalog" 70 if [ "$cdcatnum" != "" ]; then 71 echo " l) List tracks on $cdtitle" 72 echo " r) Remove $cdtitle" 73 echo " u) Update track information for $cdtitle" 74 fi 75 echo " q) Quit" 76 echo 77 echo -e "Please enter choice then press return \c" 78 read menu_choice 79 return 80 } 81 82 # Two more very short functions, insert_title and insert_track for adding to the database files. 83 # Though some people hate one-liners like these, they help make other functions clearer 84 # They are followed by the larger add_record_track function that uses them. 85 # This function uses pattern matching to ensure no commas are entered (since we're using commas 86 # as a field separator), and also arithmetic operations to increment the current track number 87 # as tracks are entered. 88 89 insert_title() { 90 echo $* >> $title_file 91 return 92 } 93 94 insert_track() { 95 echo $* >> $tracks_file 96 return 97 } 98 99 add_record_tracks() { 100 echo "Enter track information for this CD" 101 echo "When no more tracks enter q" 102 cdtrack=1 103 cdttitle="" 104 while [ "$cdttitle" != "q" ] 105 do 106 echo -e "Track $cdtrack, track title? \c" 107 read tmp 108 cdttitle=${tmp%%,*} 109 if [ "$tmp" != "$cdttitle" ]; then 110 echo "Sorry, no commas allowed" 111 continue 112 fi 113 if [ -n "$cdttitle" ] ; then 114 if [ "$cdttitle" != "q" ]; then 115 insert_track $cdcatnum,$cdtrack,$cdttitle 116 fi 117 else 118 cdtrack=$((cdtrack-1)) 119 fi 120 cdtrack=$((cdtrack+1)) 121 done 122 } 123 124 # The add_records function allows entry of the main CD information for a new CD. 125 126 add_records() { 127 # Prompt for the initial information 128 129 echo -e "Enter catalog name \c" 130 read tmp 131 cdcatnum=${tmp%%,*} 132 133 echo -e "Enter title \c" 134 read tmp 135 cdtitle=${tmp%%,*} 136 137 echo -e "Enter type \c" 138 read tmp 139 cdtype=${tmp%%,*} 140 141 echo -e "Enter artist/composer \c" 142 read tmp 143 cdac=${tmp%%,*} 144 145 # Check that they want to enter the information 146 147 echo About to add new entry 148 echo "$cdcatnum $cdtitle $cdtype $cdac" 149 150 # If confirmed then append it to the titles file 151 152 if get_confirm ; then 153 insert_title $cdcatnum,$cdtitle,$cdtype,$cdac 154 add_record_tracks 155 else 156 remove_records 157 fi 158 159 return 160 } 161 162 # The find_cd function searches for the catalog name text in the CD title file, using the 163 # grep command. We need to know how many times the string was found, but grep only returns 164 # a value telling us if it matched zero times or many. To get around this, we store the 165 # output in a file, which will have one line per match, then count the lines in the file. 166 # The word count command, wc, has whitespace in its output, separating the number of lines, 167 # words and characters in the file. We use the $(wc -l $temp_file) notation to extract the 168 # first parameter from the output to set the linesfound variable. If we wanted another, 169 # later parameter we would use the set command to set the shell's parameter variables to 170 # the command output. 171 # We change the IFS (Internal Field Separator) to a , (comma), so we can separate the 172 # comma-delimited fields. An alternative command is cut. 173 174 find_cd() { 175 if [ "$1" = "n" ]; then 176 asklist=n 177 else 178 asklist=y 179 fi 180 cdcatnum="" 181 echo -e "Enter a string to search for in the CD titles \c" 182 read searchstr 183 if [ "$searchstr" = "" ]; then 184 return 0 185 fi 186 187 grep "$searchstr" $title_file > $temp_file 188 189 set $(wc -l $temp_file) 190 linesfound=$1 191 192 case "$linesfound" in 193 0) echo "Sorry, nothing found" 194 get_return 195 return 0 196 ;; 197 1) ;; 198 2) echo "Sorry, not unique." 199 echo "Found the following" 200 cat $temp_file 201 get_return 202 return 0 203 esac 204 205 IFS="," 206 read cdcatnum cdtitle cdtype cdac < $temp_file 207 IFS=" " 208 209 if [ -z "$cdcatnum" ]; then 210 echo "Sorry, could not extract catalog field from $temp_file" 211 get_return 212 return 0 213 fi 214 215 echo 216 echo Catalog number: $cdcatnum 217 echo Title: $cdtitle 218 echo Type: $cdtype 219 echo Artist/Composer: $cdac 220 echo 221 get_return 222 223 if [ "$asklist" = "y" ]; then 224 echo -e "View tracks for this CD? \c" 225 read x 226 if [ "$x" = "y" ]; then 227 echo 228 list_tracks 229 echo 230 fi 231 fi 232 return 1 233 } 234 235 # update_cd allows us to re-enter information for a CD. Notice that we search (grep) 236 # for lines that start (^) with the $cdcatnum followed by a ,, and that we need to wrap 237 # the expansion of $cdcatnum in {} so we can search for a , with no whitespace between 238 # it and the catalogue number. This function also uses {} to enclose multiple statements 239 # to be executed if get_confirm returns true. 240 241 update_cd() { 242 if [ -z "$cdcatnum" ]; then 243 echo "You must select a CD first" 244 find_cd n 245 fi 246 if [ -n "$cdcatnum" ]; then 247 echo "Current tracks are :-" 248 list_tracks 249 echo 250 echo "This will re-enter the tracks for $cdtitle" 251 get_confirm && { 252 grep -v "^${cdcatnum}," $tracks_file > $temp_file 253 mv $temp_file $tracks_file 254 echo 255 add_record_tracks 256 } 257 fi 258 return 259 } 260 261 # count_cds gives us a quick count of the contents of our database. 262 263 count_cds() { 264 set $(wc -l $title_file) 265 num_titles=$1 266 set $(wc -l $tracks_file) 267 num_tracks=$1 268 echo found $num_titles CDs, with a total of $num_tracks tracks 269 get_return 270 return 271 } 272 273 # remove_records strips entries from the database files, using grep -v to remove all 274 # matching strings. Notice we must use a temporary file. 275 # If we tried to do this, 276 # grep -v "^$cdcatnum" > $title_file 277 # the $title_file would be set to empty by the > output redirection before the grep 278 # had chance to execute, so grep would read from an empty file. 279 280 remove_records() { 281 if [ -z "$cdcatnum" ]; then 282 echo You must select a CD first 283 find_cd n 284 fi 285 if [ -n "$cdcatnum" ]; then 286 echo "You are about to delete $cdtitle" 287 get_confirm && { 288 grep -v "^${cdcatnum}," $title_file > $temp_file 289 mv $temp_file $title_file 290 grep -v "^${cdcatnum}," $tracks_file > $temp_file 291 mv $temp_file $tracks_file 292 cdcatnum="" 293 echo Entry removed 294 } 295 get_return 296 fi 297 return 298 } 299 300 # List_tracks again uses grep to extract the lines we want, cut to access the fields 301 # we want and then more to provide a paginated output. If you consider how many lines 302 # of C code it would take to re-implement these 20-odd lines of code, you'll appreciate 303 # how powerful a tool the shell can be. 304 305 list_tracks() { 306 if [ "$cdcatnum" = "" ]; then 307 echo no CD selected yet 308 return 309 else 310 grep "^${cdcatnum}," $tracks_file > $temp_file 311 num_tracks=$(wc -l $temp_file) 312 if [ "$num_tracks" = "0" ]; then 313 echo no tracks found for $cdtitle 314 else { 315 echo 316 echo "$cdtitle :-" 317 echo 318 cut -f 2- -d , $temp_file 319 echo 320 } | ${PAGER:-more} 321 fi 322 fi 323 get_return 324 return 325 } 326 327 # Now all the functions have been defined, we can enter the main routine. 328 # The first few lines simply get the files into a known state, then we call the menu 329 # function, set_menu_choice, and act on the output. 330 # When quit is selected, we delete the temporary file, write a message and exit 331 # with a successful completion condition. 332 333 rm -f $temp_file 334 if [ ! -f $title_file ]; then 335 touch $title_file 336 fi 337 if [ ! -f $tracks_file ]; then 338 touch $tracks_file 339 fi 340 341 # Now the application proper 342 343 clear 344 echo 345 echo 346 echo "Mini CD manager" 347 sleep 1 348 349 quit=n 350 while [ "$quit" != "y" ]; 351 do 352 set_menu_choice 353 case "$menu_choice" in 354 a) add_records;; 355 r) remove_records;; 356 f) find_cd y;; 357 u) update_cd;; 358 c) count_cds;; 359 l) list_tracks;; 360 b) 361 echo 362 more $title_file 363 echo 364 get_return;; 365 q | Q ) quit=y;; 366 *) echo "Sorry, choice not recognized";; 367 esac 368 done 369 370 # Tidy up and leave 371 372 rm -f $temp_file 373 echo "Finished" 374 375 exit 0
相关文章推荐
- Shell 循环中实现展示进度百分比的脚本方法
- shell脚本中echo显示内容带颜色的实现方法
- linux下采用shell脚本实现批量为指定文件夹下图片添加水印的方法
- shell脚本中echo显示内容带颜色的实现方法
- Shell脚本实现随机数多种方法介绍(date、random、uuid)
- shell脚本中echo显示内容带颜色的实现方法
- 通过shell脚本实现从文件中读取数据的几种方法
- shell脚本中echo显示内容带颜色的实现方法
- linux下采用shell脚本实现批量为指定文件夹下图片添加水印的方法
- shell脚本里实现带参数函数的方法
- linux c程序中获取shell脚本输出的实现方法
- linux c程序中获取shell脚本输出的实现方法
- shell脚本中echo显示内容带颜色的实现方法
- linux c程序中获取shell脚本输出的实现方法
- shell 脚本中实现字符串大小写不敏感的比较方法
- Shell脚本实现乱序排列文件内容的多种方法(洗牌问题)
- Shell脚本中实现把输入的密码转换为*(星号)的方法
- shell脚本中实现大段代码的注释方法
- Shell脚本实现随机数多种方法介绍(date、random、uuid)