- •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
Redirecting Code Blocks
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 16. I/O Redirection |
Next |
16.2. Redirecting Code Blocks
Blocks of code, such as while, until, and for loops, even if/then test blocks can also incorporate redirection of stdin. Even a function may use this form of redirection (see Example 23-7). The < operator at the end of the code block accomplishes this.
Example 16-4. Redirected while loop
#!/bin/bash
if [ -z "$1" ] then
Filename=names.data # Default, if no filename specified. else
Filename=$1
fi
#+ Filename=${1:-names.data}
# can replace the above test (parameter substitution).
count=0
echo
while [ "$name" != Smith ] do
read name echo $name
let "count += 1" done <"$Filename"
#^^^^^^^^^^^^
#Why is variable $name in quotes?
#Reads from $Filename, rather than stdin.
#Redirects stdin to file $Filename.
echo; echo "$count names read"; echo
#Note that in some older shell scripting languages, #+ the redirected loop would run as a subshell.
#Therefore, $count would return 0, the initialized value outside the loop.
#Bash and ksh avoid starting a subshell whenever possible,
#+so that this script, for example, runs correctly.
#
# Thanks to Heiner Steven for pointing this out.
exit 0
Example 16-5. Alternate form of redirected while loop
http://tldp.org/LDP/abs/html/redircb.html (1 of 6) [7/15/2002 6:35:15 PM]
Redirecting Code Blocks
#!/bin/bash
#This is an alternate form of the preceding script.
#Suggested by Heiner Steven
#+ as a workaround in those situations when a redirect loop
#+ runs as a subshell, and therefore variables inside the loop
# +do not keep their values upon loop termination.
if [ -z "$1" ] |
|
|
then |
|
|
|
Filename=names.data |
# Default, if no filename specified. |
else |
|
|
|
Filename=$1 |
|
fi |
|
|
exec 3<&0 |
# Save stdin to file descriptor 3. |
|
exec 0<"$Filename" |
# Redirect standard input. |
|
count=0 |
|
|
echo |
|
|
while [ "$name" != Smith ] |
|
|
do |
|
|
|
read name |
# Reads from redirected stdin ($Filename). |
|
echo $name |
|
|
let "count += 1" |
|
done <"$Filename" |
# Loop reads from file $Filename. |
|
# |
^^^^^^^^^^^^ |
|
exec 0<&3 |
# Restore old stdin. |
|
exec 3<&- |
# Close temporary fd 3. |
echo; echo "$count names read"; echo
exit 0
Example 16-6. Redirected until loop
http://tldp.org/LDP/abs/html/redircb.html (2 of 6) [7/15/2002 6:35:15 PM]
Redirecting Code Blocks
#!/bin/bash
# Same as previous example, but with "until" loop.
if [ -z "$1" ] |
|
|
then |
|
|
Filename=names.data |
# Default, if |
no filename specified. |
else |
|
|
Filename=$1 |
|
|
fi |
|
|
# while [ "$name" != Smith ] |
|
|
until [ "$name" = Smith ] |
# Change != |
to =. |
do |
|
|
read name |
# Reads from $Filename, rather than stdin. |
|
echo $name |
|
|
done <"$Filename" |
# Redirects stdin to file $Filename. |
#^^^^^^^^^^^^
#Same results as with "while" loop in previous example.
exit 0
Example 16-7. Redirected for loop
#!/bin/bash
if [ -z "$1" ] then
Filename=names.data # Default, if no filename specified. else
Filename=$1
fi
line_count=`wc $Filename | awk '{ print $1 }'`
#Number of lines in target file.
#Very contrived and kludgy, nevertheless shows that
#+ it's possible to redirect stdin within a "for" loop...
#+ if you're clever enough.
#
# More concise is line_count=$(wc < "$Filename")
for name in `seq $line_count`
# while [ "$name" != Smith ] do
read name echo $name
if [ "$name" = Smith ] then
break
fi
# Recall that "seq" prints |
sequence of numbers. |
-- more complicated than |
a "while" loop -- |
#Reads from $Filename, rather than stdin.
#Need all this extra baggage here.
http://tldp.org/LDP/abs/html/redircb.html (3 of 6) [7/15/2002 6:35:15 PM]
Redirecting Code Blocks
done |
<"$Filename" |
# Redirects stdin to file $Filename. |
# |
^^^^^^^^^^^^ |
|
exit |
0 |
|
|
|
|
We can modify the previous example to also redirect the output of the loop.
Example 16-8. Redirected for loop (both stdin and stdout redirected)
#!/bin/bash |
|
if [ -z "$1" ] |
|
then |
|
Filename=names.data |
# Default, if no filename specified. |
else |
|
Filename=$1 |
|
fi |
|
Savefile=$Filename.new |
# Filename to save results in. |
FinalName=Jonah |
# Name to terminate "read" on. |
line_count=`wc $Filename | awk '{ print $1 }'` # Number of lines in target file.
for name in `seq $line_count` do
|
read |
name |
|
|
echo |
"$name" |
|
|
if [ |
"$name" = "$FinalName" ] |
|
|
then |
|
|
|
break |
|
|
|
fi |
|
|
done < |
"$Filename" > "$Savefile" |
# Redirects stdin to file $Filename, |
|
# |
^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
and saves it to backup file. |
exit 0
Example 16-9. Redirected if/then test
http://tldp.org/LDP/abs/html/redircb.html (4 of 6) [7/15/2002 6:35:15 PM]
Redirecting Code Blocks
#!/bin/bash |
|
|
if [ -z "$1" ] |
|
|
then |
|
|
Filename=names.data |
# Default, if no filename specified. |
|
else |
|
|
Filename=$1 |
|
|
fi |
|
|
TRUE=1 |
|
|
if [ "$TRUE" ] |
# if true |
and if : also work. |
then |
|
|
read name |
|
|
echo $name |
|
|
fi <"$Filename" |
|
|
#^^^^^^^^^^^^
#Reads only first line of file.
#An "if/then" test has no way of iterating unless embedded in a loop.
exit 0
Example 16-10. Data file "names.data" for above examples
Aristotle
Belisarius
Capablanca
Euler
Goethe
Hamurabi
Jonah
Laplace
Maroczy
Purcell
Schmidt
Semmelweiss
Smith
Turing
Venn
Wilson
Znosko-Borowski
#This is a data file for
#+ "redir2.sh", "redir3.sh", "redir4.sh", "redir4a.sh", "redir5.sh".
Redirecting the stdout of a code block has the effect of saving its output to a file. See Example 4-2.
Here documents are a special case of redirected code blocks.
http://tldp.org/LDP/abs/html/redircb.html (5 of 6) [7/15/2002 6:35:15 PM]
Redirecting Code Blocks
Prev |
Home |
Next |
Using exec |
Up |
Applications |
http://tldp.org/LDP/abs/html/redircb.html (6 of 6) [7/15/2002 6:35:15 PM]