The current version of Bash, the one you have running on your machine, is version 2.xx.y or 3.xx.y.
bash$ echo $BASH_VERSION 2.05.b.0(1)-release |
Example 35-1. String expansion
1 #!/bin/bash 2 3 # String expansion. 4 # Introduced with version 2 of Bash. 5 6 # Strings of the form $'xxx' 7 #+ have the standard escaped characters interpreted. 8 9 echo $'Ringing bell 3 times \a \a \a' 10 # May only ring once with certain terminals. 11 echo $'Three form feeds \f \f \f' 12 echo $'10 newlines \n\n\n\n\n\n\n\n\n\n' 13 echo $'\102\141\163\150' # Bash 14 # Octal equivalent of characters. 15 16 exit 0 |
Example 35-2. Indirect variable references - the new way
1 #!/bin/bash 2 3 # Indirect variable referencing. 4 # This has a few of the attributes of references in C++. 5 6 7 a=letter_of_alphabet 8 letter_of_alphabet=z 9 10 echo "a = $a" # Direct reference. 11 12 echo "Now a = ${!a}" # Indirect reference. 13 # The ${!variable} notation is greatly superior to the old "eval var1=\$$var2" 14 15 echo 16 17 t=table_cell_3 18 table_cell_3=24 19 echo "t = ${!t}" # t = 24 20 table_cell_3=387 21 echo "Value of t changed to ${!t}" # 387 22 23 # This is useful for referencing members of an array or table, 24 #+ or for simulating a multi-dimensional array. 25 # An indexing option would have been nice (sigh). 26 27 exit 0 |
Example 35-3. Simple database application, using indirect variable referencing
1 #!/bin/bash 2 # resistor-inventory.sh 3 # Simple database application using indirect variable referencing. 4 5 # ============================================================== # 6 # Data 7 8 B1723_value=470 # Ohms 9 B1723_powerdissip=.25 # Watts 10 B1723_colorcode="yellow-violet-brown" # Color bands 11 B1723_loc=173 # Where they are 12 B1723_inventory=78 # How many 13 14 B1724_value=1000 15 B1724_powerdissip=.25 16 B1724_colorcode="brown-black-red" 17 B1724_loc=24N 18 B1724_inventory=243 19 20 B1725_value=10000 21 B1725_powerdissip=.25 22 B1725_colorcode="brown-black-orange" 23 B1725_loc=24N 24 B1725_inventory=89 25 26 # ============================================================== # 27 28 29 echo 30 31 PS3='Enter catalog number: ' 32 33 echo 34 35 select catalog_number in "B1723" "B1724" "B1725" 36 do 37 Inv=${catalog_number}_inventory 38 Val=${catalog_number}_value 39 Pdissip=${catalog_number}_powerdissip 40 Loc=${catalog_number}_loc 41 Ccode=${catalog_number}_colorcode 42 43 echo 44 echo "Catalog number $catalog_number:" 45 echo "There are ${!Inv} of [${!Val} ohm / ${!Pdissip} watt] resistors in stock." 46 echo "These are located in bin # ${!Loc}." 47 echo "Their color code is \"${!Ccode}\"." 48 49 break 50 done 51 52 echo; echo 53 54 # Exercises: 55 # --------- 56 # 1) Rewrite this script to read its data from an external file. 57 # 2) Rewrite this script to use arrays, 58 #+ rather than indirect variable referencing. 59 # Which method is more straightforward and intuitive? 60 61 62 # Notes: 63 # ----- 64 # Shell scripts are inappropriate for anything except the most simple 65 #+ database applications, and even then it involves workarounds and kludges. 66 # Much better is to use a language with native support for data structures, 67 #+ such as C++ or Java (or even Perl). 68 69 exit 0 |
Example 35-4. Using arrays and other miscellaneous trickery to deal four random hands from a deck of cards
1 #!/bin/bash 2 # May need to be invoked with #!/bin/bash2 on older machines. 3 4 # Cards: 5 # Deals four random hands from a deck of cards. 6 7 UNPICKED=0 8 PICKED=1 9 10 DUPE_CARD=99 11 12 LOWER_LIMIT=0 13 UPPER_LIMIT=51 14 CARDS_IN_SUIT=13 15 CARDS=52 16 17 declare -a Deck 18 declare -a Suits 19 declare -a Cards 20 # It would have been easier and more intuitive 21 #+ with a single, 3-dimensional array. 22 # Perhaps a future version of Bash will support multidimensional arrays. 23 24 25 initialize_Deck () 26 { 27 i=$LOWER_LIMIT 28 until [ "$i" -gt $UPPER_LIMIT ] 29 do 30 Deck[i]=$UNPICKED # Set each card of "Deck" as unpicked. 31 let "i += 1" 32 done 33 echo 34 } 35 36 initialize_Suits () 37 { 38 Suits[0]=C #Clubs 39 Suits[1]=D #Diamonds 40 Suits[2]=H #Hearts 41 Suits[3]=S #Spades 42 } 43 44 initialize_Cards () 45 { 46 Cards=(2 3 4 5 6 7 8 9 10 J Q K A) 47 # Alternate method of initializing an array. 48 } 49 50 pick_a_card () 51 { 52 card_number=$RANDOM 53 let "card_number %= $CARDS" 54 if [ "${Deck[card_number]}" -eq $UNPICKED ] 55 then 56 Deck[card_number]=$PICKED 57 return $card_number 58 else 59 return $DUPE_CARD 60 fi 61 } 62 63 parse_card () 64 { 65 number=$1 66 let "suit_number = number / CARDS_IN_SUIT" 67 suit=${Suits[suit_number]} 68 echo -n "$suit-" 69 let "card_no = number % CARDS_IN_SUIT" 70 Card=${Cards[card_no]} 71 printf %-4s $Card 72 # Print cards in neat columns. 73 } 74 75 seed_random () # Seed random number generator. 76 { # What happens if you don't do this? 77 seed=`eval date +%s` 78 let "seed %= 32766" 79 RANDOM=$seed 80 } 81 82 deal_cards () 83 { 84 echo 85 86 cards_picked=0 87 while [ "$cards_picked" -le $UPPER_LIMIT ] 88 do 89 pick_a_card 90 t=$? 91 92 if [ "$t" -ne $DUPE_CARD ] 93 then 94 parse_card $t 95 96 u=$cards_picked+1 97 # Change back to 1-based indexing (temporarily). Why? 98 let "u %= $CARDS_IN_SUIT" 99 if [ "$u" -eq 0 ] # Nested if/then condition test. 100 then 101 echo 102 echo 103 fi 104 # Separate hands. 105 106 let "cards_picked += 1" 107 fi 108 done 109 110 echo 111 112 return 0 113 } 114 115 116 # Structured programming: 117 # Entire program logic modularized in functions. 118 119 #================ 120 seed_random 121 initialize_Deck 122 initialize_Suits 123 initialize_Cards 124 deal_cards 125 #================ 126 127 exit 0 128 129 130 131 # Exercise 1: 132 # Add comments to thoroughly document this script. 133 134 # Exercise 2: 135 # Add a routine (function) to print out each hand sorted in suits. 136 # You may add other bells and whistles if you like. 137 138 # Exercise 3: 139 # Simplify and streamline the logic of the script. |
[1] | Chet Ramey promises associative arrays (a Perl feature) in a future Bash release. As of version 3, this has not yet happened. |