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. |