The current version of Bash, the one you have running on your machine, is actually version 2.XX.
bash$ echo $BASH_VERSION 2.04.21(1)-release |
Example 35-1. String expansion
#!/bin/bash # String expansion. # Introduced with version 2 of Bash. # Strings of the form $'xxx' # have the standard escaped characters interpreted. echo $'Ringing bell 3 times \a \a \a' echo $'Three form feeds \f \f \f' echo $'10 newlines \n\n\n\n\n\n\n\n\n\n' exit 0 |
Example 35-2. Indirect variable references - the new way
#!/bin/bash # Indirect variable referencing. # This has a few of the attributes of references in C++. a=letter_of_alphabet letter_of_alphabet=z echo "a = $a" # Direct reference. echo "Now a = ${!a}" # Indirect reference. # The ${!variable} notation is greatly superior to the old "eval var1=\$$var2" echo t=table_cell_3 table_cell_3=24 echo "t = ${!t}" # t = 24 table_cell_3=387 echo "Value of t changed to ${!t}" # 387 # This is useful for referencing members of an array or table, # or for simulating a multi-dimensional array. # An indexing option would have been nice (sigh). exit 0 |
Example 35-3. Simple database application, using indirect variable referencing
#!/bin/bash # resistor-inventory.sh # Simple database application using indirect variable referencing. # ============================================================== # # Data B1723_value=470 # ohms B1723_powerdissip=.25 # watts B1723_colorcode="yellow-violet-brown" # color bands B1723_loc=173 # where they are B1723_inventory=78 # how many B1724_value=1000 B1724_powerdissip=.25 B1724_colorcode="brown-black-red" B1724_loc=24N B1724_inventory=243 B1725_value=10000 B1725_powerdissip=.25 B1725_colorcode="brown-black-orange" B1725_loc=24N B1725_inventory=89 # ============================================================== # echo PS3='Enter catalog number: ' echo select catalog_number in "B1723" "B1724" "B1725" do Inv=${catalog_number}_inventory Val=${catalog_number}_value Pdissip=${catalog_number}_powerdissip Loc=${catalog_number}_loc Ccode=${catalog_number}_colorcode echo echo "Catalog number $catalog_number:" echo "There are ${!Inv} of [${!Val} ohm / ${!Pdissip} watt] resistors in stock." echo "These are located in bin # ${!Loc}." echo "Their color code is \"${!Ccode}\"." break done echo; echo # Exercise: # -------- # Rewrite this script using arrays, rather than indirect variable referencing. # Which method is more straightforward and intuitive? # Notes: # ----- # Shell scripts are inappropriate for anything except the most simple #+ database applications, and even then it involves workarounds and kludges. # Much better is to use a language with native support for data structures, #+ such as C++ or Java (or even Perl). exit 0 |
Example 35-4. Using arrays and other miscellaneous trickery to deal four random hands from a deck of cards
#!/bin/bash # May need to be invoked with #!/bin/bash2 on older machines. # Cards: # deals four random hands from a deck of cards. UNPICKED=0 PICKED=1 DUPE_CARD=99 LOWER_LIMIT=0 UPPER_LIMIT=51 CARDS_IN_SUIT=13 CARDS=52 declare -a Deck declare -a Suits declare -a Cards # It would have been easier and more intuitive # with a single, 3-dimensional array. # Perhaps a future version of Bash will support multidimensional arrays. initialize_Deck () { i=$LOWER_LIMIT until [ "$i" -gt $UPPER_LIMIT ] do Deck[i]=$UNPICKED # Set each card of "Deck" as unpicked. let "i += 1" done echo } initialize_Suits () { Suits[0]=C #Clubs Suits[1]=D #Diamonds Suits[2]=H #Hearts Suits[3]=S #Spades } initialize_Cards () { Cards=(2 3 4 5 6 7 8 9 10 J Q K A) # Alternate method of initializing an array. } pick_a_card () { card_number=$RANDOM let "card_number %= $CARDS" if [ "${Deck[card_number]}" -eq $UNPICKED ] then Deck[card_number]=$PICKED return $card_number else return $DUPE_CARD fi } parse_card () { number=$1 let "suit_number = number / CARDS_IN_SUIT" suit=${Suits[suit_number]} echo -n "$suit-" let "card_no = number % CARDS_IN_SUIT" Card=${Cards[card_no]} printf %-4s $Card # Print cards in neat columns. } seed_random () # Seed random number generator. { seed=`eval date +%s` let "seed %= 32766" RANDOM=$seed } deal_cards () { echo cards_picked=0 while [ "$cards_picked" -le $UPPER_LIMIT ] do pick_a_card t=$? if [ "$t" -ne $DUPE_CARD ] then parse_card $t u=$cards_picked+1 # Change back to 1-based indexing (temporarily). let "u %= $CARDS_IN_SUIT" if [ "$u" -eq 0 ] # Nested if/then condition test. then echo echo fi # Separate hands. let "cards_picked += 1" fi done echo return 0 } # Structured programming: # entire program logic modularized in functions. #================ seed_random initialize_Deck initialize_Suits initialize_Cards deal_cards exit 0 #================ # Exercise 1: # Add comments to thoroughly document this script. # Exercise 2: # Revise the script to print out each hand sorted in suits. # You may add other bells and whistles if you like. # Exercise 3: # Simplify and streamline the logic of the script. |
[1] | Chet Ramey promises associative arrays (a Perl feature) in a future Bash release. |