《Beginning Linux Programming》读书笔记(二)

      2Shell编程没什么多说的,记录个代码,本章最后的那个简单的CD管理程序

# !/ bin / sh

# Very simple example shell script 
for  managing a CD collection.
# Copyright (C) 
1996 - 99  Wrox Press.

# This program 
is  free software; you can redistribute it and / or modify it
# under the terms of the GNU General Public License 
as  published by the
# Free Software Foundation; either version 
2  of the License, or (at your
# option) any later version.

# This program 
is  distributed  in  the hopes that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License 
for  more details.

# You should have received a copy of the GNU General Public License along
# with 
this  program;  if  not, write to the Free Software Foundation, Inc.
675  Mass Ave, Cambridge, MA  02139 , USA.

# The first thing to 
do   is  to ensure that some  global  variables that we ' ll be using
# throughout the script are  set  up. We  set  the title and track files and a temporary file.
# We also trap Ctrl
- C, so our temporary file  is  removed  if  the user interrupts the script.

menu_choice
= ""
current_cd
= ""
title_file
= " title.cdb "
tracks_file
= " tracks.cdb "
temp_file
=/ tmp / cdb.$$
trap 
' rm -f $temp_file '  EXIT

# Now we define our functions, so that the script, executing from the top line, can find
# all the function definitions before we attempt to call any of them 
for  the first time.
# To avoid rewriting the same code 
in  several places, the first two functions are simple
# utilities.

get_return() {
  echo 
- " Press return /c "
  read x
  
return   0
}

get_confirm() {
  echo 
- " 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
}

# 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 
- " Please enter choice then press return /c "
  read menu_choice
  
return
}

# Two more very 
short  functions, insert_title and insert_track  for  adding to the database files.
# Though some people hate one
- liners like these, they help make other functions clearer
# They are followed by the larger add_record_track function that uses them.
# This function uses pattern matching to ensure no commas are entered (since we
' re using commas
as  a field separator), and also arithmetic operations to increment the current track number
as  tracks are entered.

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 "
  cdtrack
= 1
  cdttitle
= ""
  
while  [  " $cdttitle "   !=   " q "  ]
  
do
      echo 
- " Track $cdtrack, track title? /c "
      read tmp
      cdttitle
= ${tmp %% , * }
      
if  [  " $tmp "   !=   " $cdttitle "  ]; then
        echo 
" Sorry, no commas allowed "
        
continue
      fi
      
if  [  - " $cdttitle "  ] ; then
        
if  [  " $cdttitle "   !=   " q "  ]; then
          insert_track $cdcatnum,$cdtrack,$cdttitle
        fi
      
else
        cdtrack
= $((cdtrack - 1 ))
      fi
    cdtrack
= $((cdtrack + 1 ))
  done
}

# The add_records function allows entry of the main CD information 
for  a  new  CD.

add_records() {
  # Prompt 
for  the initial information

  echo 
- " Enter catalog name /c "
  read tmp
  cdcatnum
= ${tmp %% , * }

  echo 
- " Enter title /c "
  read tmp
  cdtitle
= ${tmp %% , * }

  echo 
- " Enter type /c "
  read tmp
  cdtype
= ${tmp %% , * }

  echo 
- " Enter artist/composer /c "
  read tmp
  cdac
= ${tmp %% , * }

  # Check that they want to enter the information
  
  echo About to add 
new  entry
  echo 
" $cdcatnum $cdtitle $cdtype $cdac "

  # If confirmed then append it to the titles file
  
  
if  get_confirm ; then
    insert_title $cdcatnum,$cdtitle,$cdtype,$cdac
    add_record_tracks
  
else
    remove_records
  fi 

  
return
}

# The find_cd function searches 
for  the catalog name text  in  the CD title file,  using  the
# grep command. We need to know how many times the 
string  was found, but grep only returns
# a value telling us 
if  it matched zero times or many. To  get  around  this , we store the
# output 
in  a file, which will have one line per match, then count the lines  in  the file.
# The word count command, wc, has whitespace 
in  its output, separating the number of lines,
# words and characters 
in  the file. We use the $(wc  - l $temp_file) notation to extract the
# first parameter from the output to 
set  the linesfound variable. If we wanted another,
# later parameter we would use the 
set  command to  set  the shell ' s parameter variables to
# the command output.
# We change the IFS (Internal Field Separator) to a , (comma), so we can separate the
# comma
- delimited fields. An alternative command  is  cut.

find_cd() {
  
if  [  " $1 "   =   " n "  ]; then
    asklist
= n
  
else
    asklist
= y
  fi
  cdcatnum
= ""
  echo 
- " 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  [  - " $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 
- " View tracks for this CD? /c "
      read x
    
if  [  " $x "   =   " y "  ]; then
      echo
      list_tracks
      echo
    fi
  fi
  
return   1
}

# update_cd allows us to re
- enter information  for  a CD. Notice that we search (grep)
for  lines that start ( ^ ) with the $cdcatnum followed by a ,, and that we need to wrap
# the expansion of $cdcatnum 
in  {} so we can search  for  a , with no whitespace between
# it and the catalogue number. This function also uses {} to enclose multiple statements
# to be executed 
if  get_confirm returns  true .

update_cd() {
  
if  [  - " $cdcatnum "  ]; then
    echo 
" You must select a CD first "
    find_cd n
  fi
  
if  [  - " $cdcatnum "  ]; then
    echo 
" Current tracks are :- "
    list_tracks
    echo
    echo 
" This will re-enter the tracks for $cdtitle "
    get_confirm 
&&  {
      grep 
- " ^${cdcatnum}, "  $tracks_file  >  $temp_file
      mv $temp_file $tracks_file
      echo
      add_record_tracks
    }
  fi
  
return
}

# count_cds gives us a quick count of the contents of our database.

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 of $num_tracks tracks
  get_return
  
return
}

# remove_records strips entries from the database files, 
using  grep  - v to remove all
# matching strings. Notice we must use a temporary file.
# If we tried to 
do   this ,
# grep 
- " ^$cdcatnum "   >  $title_file
# the $title_file would be 
set  to empty by the  >  output redirection before the grep
# had chance to execute, so grep would read from an empty file.

remove_records() {
  
if  [  - " $cdcatnum "  ]; then
    echo You must select a CD first
    find_cd n
  fi
  
if  [  - " $cdcatnum "  ]; then
    echo 
" You are about to delete $cdtitle "
    get_confirm 
&&  {
      grep 
- " ^${cdcatnum}, "  $title_file  >  $temp_file
      mv $temp_file $title_file
      grep 
- " ^${cdcatnum}, "  $tracks_file  >  $temp_file
      mv $temp_file $tracks_file
      cdcatnum
= ""
      echo Entry removed
    }
    get_return
  fi
  
return
}

# List_tracks again uses grep to extract the lines we want, cut to access the fields
# we want and then more to provide a paginated output. If you consider how many lines
# of C code it would take to re
- implement these  20 - odd lines of code, you ' ll appreciate
# how powerful a tool the shell can be.

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 
- 2 -   - d , $temp_file 
      echo 
    } 
|  ${PAGER: - more}
    fi
  fi
  get_return
  
return
}

# Now all the functions have been defined, we can enter the main routine.
# The first few lines simply 
get  the files into a known state, then we call the menu
# function, set_menu_choice, and act on the output.
# When quit 
is  selected, we delete the temporary file, write a message and exit
# with a successful completion condition.

rm 
- f $temp_file
if  [  !   - f $title_file ]; then
  touch $title_file
fi
if  [  !   - f $tracks_file ]; then
  touch $tracks_file
fi

# 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值