- •Advanced Bash-Scripting Guide
- •Dedication
- •Table of Contents
- •Part 1. Introduction
- •Advanced Bash-Scripting Guide
- •Chapter 2. Starting Off With a Sha-Bang
- •2.1. Invoking the script
- •2.2. Preliminary Exercises
- •Part 2. Basics
- •Chapter 3. Exit and Exit Status
- •Chapter 4. Special Characters
- •Chapter 5. Introduction to Variables and Parameters
- •5.1. Variable Substitution
- •5.2. Variable Assignment
- •5.3. Bash Variables Are Untyped
- •5.4. Special Variable Types
- •Chapter 6. Quoting
- •Chapter 7. Tests
- •7.1. Test Constructs
- •7.2. File test operators
- •7.3. Comparison operators (binary)
- •7.4. Nested if/then Condition Tests
- •7.5. Testing Your Knowledge of Tests
- •8.1. Operators
- •8.2. Numerical Constants
- •Part 3. Beyond the Basics
- •Chapter 9. Variables Revisited
- •9.1. Internal Variables
- •9.2. Manipulating Strings
- •9.3. Parameter Substitution
- •9.4. Typing variables: declare or typeset
- •9.5. Indirect References to Variables
- •9.6. $RANDOM: generate random integer
- •9.7. The Double Parentheses Construct
- •Chapter 10. Loops and Branches
- •10.1. Loops
- •10.2. Nested Loops
- •10.3. Loop Control
- •10.4. Testing and Branching
- •Chapter 11. Internal Commands and Builtins
- •12.1. Basic Commands
- •12.2. Complex Commands
- •12.3. Time / Date Commands
- •12.4. Text Processing Commands
- •12.5. File and Archiving Commands
- •12.6. Communications Commands
- •12.7. Terminal Control Commands
- •12.8. Math Commands
- •12.9. Miscellaneous Commands
- •Chapter 13. System and Administrative Commands
- •Chapter 14. Command Substitution
- •Chapter 15. Arithmetic Expansion
- •Chapter 16. I/O Redirection
- •16.1. Using exec
- •16.2. Redirecting Code Blocks
- •16.3. Applications
- •Chapter 17. Here Documents
- •Chapter 18. Recess Time
- •Part 4. Advanced Topics
- •Chapter 19. Regular Expressions
- •19.1. A Brief Introduction to Regular Expressions
- •19.2. Globbing
- •Chapter 20. Subshells
- •Chapter 21. Restricted Shells
- •Chapter 22. Process Substitution
- •Chapter 23. Functions
- •23.1. Complex Functions and Function Complexities
- •23.2. Local Variables
- •Chapter 24. Aliases
- •Chapter 25. List Constructs
- •Chapter 26. Arrays
- •Chapter 27. Files
- •Chapter 28. /dev and /proc
- •28.2. /proc
- •Chapter 29. Of Zeros and Nulls
- •Chapter 30. Debugging
- •Chapter 31. Options
- •Chapter 32. Gotchas
- •Chapter 33. Scripting With Style
- •Chapter 34. Miscellany
- •34.2. Shell Wrappers
- •34.3. Tests and Comparisons: Alternatives
- •34.4. Optimizations
- •34.5. Assorted Tips
- •34.6. Oddities
- •34.7. Security Issues
- •34.8. Portability Issues
- •34.9. Shell Scripting Under Windows
- •Chapter 35. Bash, version 2
- •36. Endnotes
- •36.1. Author's Note
- •36.2. About the Author
- •36.3. Tools Used to Produce This Book
- •36.4. Credits
- •List of Tables
- •List of Examples
- •Bibliography
Bash, version 2
Advanced Bash-Scripting Guide:
Prev |
Next |
Chapter 35. Bash, version 2
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
This update of the classic Bash scripting language added array variables, [1] string and parameter expansion, and a better method of indirect variable references, among other features.
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
http://tldp.org/LDP/abs/html/bash2.html (1 of 6) [7/15/2002 6:34:20 PM]
Bash, version 2
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
http://tldp.org/LDP/abs/html/bash2.html (2 of 6) [7/15/2002 6:34:20 PM]
Bash, version 2
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 ()
{
http://tldp.org/LDP/abs/html/bash2.html (3 of 6) [7/15/2002 6:34:20 PM]
Bash, version 2
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
}
http://tldp.org/LDP/abs/html/bash2.html (4 of 6) [7/15/2002 6:34:20 PM]
Bash, version 2
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.
http://tldp.org/LDP/abs/html/bash2.html (5 of 6) [7/15/2002 6:34:20 PM]
Bash, version 2
#Exercise 3:
#Simplify and streamline the logic of the script.
Notes
[1]Chet Ramey promises associative arrays (a Perl feature) in a future Bash release.
Prev |
Home |
Next |
Shell Scripting Under Windows |
Up |
Endnotes |
http://tldp.org/LDP/abs/html/bash2.html (6 of 6) [7/15/2002 6:34:20 PM]