The current version of Bash, the one you have running on your machine, is actually version 2.XX.Y.
bash$ echo $BASH_VERSION 2.05.8(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 echo $'Three form feeds \f \f \f' 11 echo $'10 newlines \n\n\n\n\n\n\n\n\n\n' 12 13 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 # Exercise:
55 # --------
56 # Rewrite this script using arrays, rather than indirect variable referencing.
57 # Which method is more straightforward and intuitive?
58
59
60 # Notes:
61 # -----
62 # Shell scripts are inappropriate for anything except the most simple
63 #+ database applications, and even then it involves workarounds and kludges.
64 # Much better is to use a language with native support for data structures,
65 #+ such as C++ or Java (or even Perl).
66
67 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 {
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).
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 exit 0
127 #================
128
129
130
131 # Exercise 1:
132 # Add comments to thoroughly document this script.
133
134 # Exercise 2:
135 # Revise the script 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. |