This commit is contained in:
gferg 2003-11-03 16:25:16 +00:00
parent 62f6e6a995
commit 36ecdef705
38 changed files with 765 additions and 216 deletions

View File

@ -6,6 +6,127 @@
http://personal.riverusers.com/~thegrendel/Change.log
------------------------------------------------------------------------
Version 2.2 'CRANBERRY' release, 11/01/03
Comments: Major release.
Much new material added.
1) In "Text Processing Commands" of "External Commands and Filters" chapter:
Fixed up listing of "gettext."
(Thanks, Bruno Haible.)
Added "msgfmt."
Renamed "du.sh" example to "Du.sh" to avoid confusion with system 'du"
command.
(Thank you, Bill Gradwohl.)
2) In "Typing Variables" section of "Variables Revisited" chapter:
At 'declare,' added example of arithmetic operations enabled
with '-i' option.
Fixed term heading to "-x var=$value." (Thank you, Bill Gradwohl.)
3) Modified "Localization" appendix, per suggestions by Bruno Haible.
4) In "Internal Variables" section of "Variables Revisited" chapter:
Added '$PROMPT_COMMAND.'
Fixed an error in "arglist.sh" example.
Added Bjön Eriksson's "readpipe.sh" example.
5) In "Local Variables" section of "Functions" chapter:
Modified note in example script in footnote 2.
(Thanks, Zhao You Bing.)
6) Fixed up references to my own "yawl" package, to reflect
the latest update.
7) In "Writing Scripts" section of "Exercises" appendix:
In "Difficult" section, added "Testing Passwords" exercise .
8) In "Subshells" chapter:
In in-line script example that tests whether variable is set,
noted that this also tests whether that variable is present
in the environment (exported).
(Thank you, Mr. Fred.)
9) In "Comparison Operations" section of "Tests" chapter:
Corrected typos in "str-test.sh" example.
(Thank you, Bill Gradwohl.)
10) In "Internal Commands" chapter:
Fixed a typo in "ex46.sh" example.
(Thank you, Bill Gradwohl.)
Fixed a typo in "ex33.sh" example,
and implemented changes to explain what OPTIND does.
(Thank you, Bill Gradwohl.)
11) In "Information and Statistics" subsection of "System and
Administrative Commands" chapter:
Substituted better example of 'sar' output.
(Thank you, Sebastien Godard.)
12) In "Local Variables " section of "Functions" chapter:
Fixed up "ex62.sh" example.
(Thank you, Bill Gradwohl.)
13) In "Basic Commands" section of "External Commands" Chapter:
Added to discussion of 'ln.'
Fixed typo in in-line example listing at 'cat,tac.'
(Thank you, Bill Gradwohl.)
14) In "Miscellaneous Commands" section of "External Commands" Chapter:
Corrected "ex33a.sh" example.
Noted that 'getopt' permits long options.
(Thank you, Eric Levy.)
15) In "RANDOM" section of "Variables Revisited" chapter:
Noted exception in "Jipe" method of generating random numbers
within a given range.
Added improved formula for generating randoms within a range.
(Thank you, Bill Gradwohl.)
Added "random-between.sh" example for generating randoms within a range.
(Thank you, Bill Gradwohl.)
16) In "Arrays" chapter:
Changed in-line example of miscellaneous array operations
to an external shell script and enhanced it, per suggestions
by Michael Zick.
Added "array-strops.sh" example of using string manipulation operations
on arrays.
Added "array-assign.bash" script.
Added "array-append.bash" script.
(Thank you, Michael Zick.)
17) In "Special Characters" chapter:
At "Control Characters," section, added Ctl-B, Ctl-I, Ctl-S, and
Ctl-K listings.
Fixed listing for Ctl-M (Thanks, Lee Maschmeyer.)
Also added Lee Maschmeyer's in-line example.
18) In "Gotchas" chapter:
At "Piping echo output . . . " inserted missing space.
19) In "Exit and Exit Status" chapter:
Added material to discussion of "bare" exit.
20) Added "Where to Go For Help" section
to "Endnotes" chapter.
21) In the "Sed and Awk Micro-primer" appendix:
Added "nyal's" "letter-count.sh" script.
22) In "Contributed Scripts" appendix:
Added Michael Zick's "protect_literal.sh" script.
Added Michael Zick's "unprotect_literal.sh" script.
Added Michael Zick's "basics-reviewed.bash" script.
23) In "Bibliography" section:
Added 'Bash Navigator' listing.
Added 'GNU Bash Reference Manual' listing (thanks, Brian Gough).
24) Miscellaneous cleanups on example scripts.
Version 2.1
'HUCKLEBERRY' release, 09/14/03
@ -17,7 +138,7 @@ Version 2.1
Added "Miscellaneous Construct" table.
Added variable prefix matching to "Parameter Substitution" table.
3) In "Internal Variables" chapter"
3) In "Internal Variables" section of "Variables Revisited" chapter:
Noted that "$*" must be quoted to differentiate it from "$@" variable,
and added a case to "arglist.sh" example to demonstrate this.
(Thanks, Heiner Steven.)
@ -139,7 +260,11 @@ bumped up to a major version. This is now officially a "mature" project.
"Quoting" chapter
"advisable in enclose it" --> "advisable to enclose it"
17) Corrected several minor typos in the text and script examples.
17) In "Copyright" chapter:
Added note about contributors rights.
Added mention of Russian translation being underway.
18) Corrected several minor typos in the text and script examples.
@ -1040,8 +1165,8 @@ Version 1.0 (stable!), released 10/14/01
o Moved "Shell Wrappers" section from "Starting Off With a Sha-Bang"
chapter to "Miscellany" chapter.
6) In "Local Variables and Recursion" section of "Functions" chapter, defined
"recursion" in more detail.
6) In "Local Variables and Recursion" section of "Functions" chapter:
Defined "recursion" in more detail.
7) Modified in-line example in "Special Variable Types" section of
"Introduction to Variables and Parameters". Thanks, John Villalovos for

View File

@ -1,9 +1,9 @@
SOME SCRIPTS WILL NOT RUN
SOME SCRIPTS WILL NOT RUN AS IS
Note that the source code for a few of the example shell scripts,
Note that the source code for some of the example shell scripts,
du.sh
Du.sh
encryptedpw.sh
ex57.sh
ex70.sh
@ -12,11 +12,13 @@ ex71a.sh
ex71b.sh
logevents.sh
m4.sh
pb.sh
pw.sh
read-r.sh
rnd.sh
rot13.sh
here-function.sh
array-assign.bash
directory-info.sh (lines 273 and 353)
bashrc (comments on lines 596 and 618)

View File

@ -182,7 +182,7 @@ Uncomment line below to generate index.
<!ENTITY pattmatching SYSTEM "patt-matching.sh">
<!ENTITY isalpha SYSTEM "isalpha.sh">
<!ENTITY rnd SYSTEM "rnd.sh">
<!ENTITY du SYSTEM "du.sh">
<!ENTITY du SYSTEM "Du.sh">
<!ENTITY refparams SYSTEM "ref-params.sh">
<!ENTITY primes SYSTEM "primes.sh">
<!ENTITY vartrace SYSTEM "vartrace.sh">
@ -273,6 +273,16 @@ Uncomment line below to generate index.
<!ENTITY embarr SYSTEM "embedded-arrays.sh">
<!ENTITY generatescript SYSTEM "generate-script.sh">
<!ENTITY scriptarray SYSTEM "script-array.sh">
<!ENTITY randombetween SYSTEM "random-between.sh">
<!ENTITY arrayops SYSTEM "array-ops.sh">
<!ENTITY arraystrops SYSTEM "array-strops.sh">
<!ENTITY arrayappend SYSTEM "array-append.bash">
<!ENTITY arrayassign SYSTEM "array-assign.bash">
<!ENTITY lettercount SYSTEM "letter-count.sh">
<!ENTITY protectliteral SYSTEM "protect_literal.sh">
<!ENTITY unprotectliteral SYSTEM "unprotect_literal.sh">
<!ENTITY basicsreviewed SYSTEM "basics-reviewed.bash">
<!ENTITY readpipe SYSTEM "readpipe.sh">
<!ENTITY usrmnt SYSTEM "usrmnt.sh">
<!ENTITY dialog SYSTEM "dialog.sh">
<!ENTITY evalex SYSTEM "eval.example">
@ -296,8 +306,8 @@ Uncomment line below to generate index.
</affiliation>
</author>
<releaseinfo>2.1</releaseinfo>
<pubdate>14 September 2003</pubdate>
<releaseinfo>2.2</releaseinfo>
<pubdate>31 October 2003</pubdate>
<revhistory>
@ -431,6 +441,13 @@ Uncomment line below to generate index.
<revremark>'HUCKLEBERRY' release: bugfixes and more material.</revremark>
</revision>
<revision>
<revnumber>2.2</revnumber>
<date>31 October 2003</date>
<authorinitials>mc</authorinitials>
<revremark>'CRANBERRY' release: Major update.</revremark>
</revision>
</revhistory>
@ -454,7 +471,7 @@ Uncomment line below to generate index.
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
including both the SGML source and
rendered HTML, may be downloaded from <ulink
url="http://personal.riverusers.com/~thegrendel/abs-guide-2.1.tar.bz2">
url="http://personal.riverusers.com/~thegrendel/abs-guide-2.2.tar.bz2">
the author's home site</ulink>. See the <ulink
url="http://personal.riverusers.com/~thegrendel/Change.log">change
log</ulink> for a revision history.</para>
@ -2676,6 +2693,11 @@ echo $a # 28</programlisting></para>
<itemizedlist id="ctlchar">
<listitem>
<para><userinput>Ctl-B</userinput></para>
<para>Backspace (nondestructive).</para>
</listitem>
<listitem>
<para><userinput>Ctl-C</userinput></para>
<para>Terminate a foreground job.</para>
@ -2697,7 +2719,7 @@ echo $a # 28</programlisting></para>
<listitem>
<para><userinput>Ctl-H</userinput></para>
<para>Backspace.</para>
<para><quote>Rubout</quote> (destructive backspace).</para>
<para>
<programlisting>#!/bin/bash
# Embedding Ctl-H in a string.
@ -2713,9 +2735,19 @@ echo; echo</programlisting>
</para>
</listitem>
<listitem>
<para><userinput>Ctl-I</userinput></para>
<para>Horizontal tab.</para>
</listitem>
<listitem>
<para><userinput>Ctl-J</userinput></para>
<para>Carriage return.</para>
<para>Newline (line feed).</para>
</listitem>
<listitem>
<para><userinput>Ctl-K</userinput></para>
<para>Vertical tab.</para>
</listitem>
<listitem>
@ -2727,10 +2759,33 @@ echo; echo</programlisting>
<listitem>
<para><userinput>Ctl-M</userinput></para>
<para>Newline.</para>
<para>Carriage return.</para>
<para>
<programlisting>#!/bin/bash
# Thank you, Lee Maschmeyer, for this example.
read -n 1 -s -p $'Control-M leaves cursor at beginning of this line. Press Enter. \x0d'
# Of course, '0d' is the hex equivalent of Control-M.
echo >&2 # The '-s' makes anything typed silent,
#+ so it is necessary to go to new line explicitly.
read -n 1 -s -p $'Control-J leaves cursor on next line. \x0a'
echo >&2 # Control-J is linefeed.
read -n 1 -s -p $'And Control-K\x0bgoes straight down.'
echo >&2 # Control-K is vertical tab.
exit 0</programlisting>
</para>
</listitem>
<listitem>
<para><userinput>Ctl-S</userinput></para>
<para>Suspend (XOFF).</para>
<para>This freezes <filename>stdin</filename> in a terminal.</para>
</listitem>
<listitem>
<para><userinput>Ctl-U</userinput></para>
<para>Erase a line of input.</para>
</listitem>
@ -3751,10 +3806,49 @@ bar' # Escape character \ taken literally because of strong quoting.
must be a decimal number in the <returnvalue>0</returnvalue> -
<returnvalue>255</returnvalue> range).</para>
<note><para>When a script ends with an <command>exit</command> that has
<note>
<para>When a script ends with an <command>exit</command> that has
no parameter, the exit status of the script is the exit status of
the last command executed in the script (<emphasis>not</emphasis>
counting the <command>exit</command>).</para></note>
counting the <command>exit</command>).</para>
<para><programlisting>#!/bin/bash
COMMAND_1
. . .
# Will exit with status of last command.
COMMAND_LAST
exit</programlisting></para>
<para>The equivalent of a bare <command>exit</command> is
<command>exit $?</command> or even just omitting the
<command>exit</command>.</para>
<para><programlisting>#!/bin/bash
COMMAND_1
. . .
# Will exit with status of last command.
COMMAND_LAST
exit $?</programlisting></para>
<para><programlisting>#!/bin/bash
COMMAND1
. . .
# Will exit with status of last command.
COMMAND_LAST</programlisting></para>
</note>
<para><anchor id="exsref"></para>
@ -6047,6 +6141,22 @@ echo "Last command argument processed = $last_cmd_arg"
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$PROMPT_COMMAND</varname></term>
<indexterm>
<primary>$PROMPT_COMMAND</primary>
</indexterm>
<indexterm>
<primary>variable</primary>
<secondary>prompt</secondary>
</indexterm>
<listitem>
<para>A variable holding a command to be executed
just before the primary prompt, <varname>$PS1</varname>
is to be displayed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><anchor id="ps1ref"><varname>$PS1</varname></term>
<indexterm>
@ -7678,21 +7788,32 @@ echo "a = $a" # a = xyz23 xyz24
<varlistentry>
<term><token>-i</token> <replaceable>integer</replaceable></term>
<listitem>
<para><programlisting>declare -i number
# The script will treat subsequent occurrences of "number" as an integer.
number=3
echo "number = $number" # number = 3
echo "Number = $number" # Number = 3
number=three
echo "number = $number" # number = 0
# Tries to evaluate "three" as an integer.</programlisting>
echo "Number = $number" # Number = 0
# Tries to evaluate the string "three" as an integer.</programlisting></para>
Note that certain arithmetic operations are permitted
<para>Certain arithmetic operations are permitted
for declared integer variables without the need
for <link linkend="exprref">expr</link> or <link
linkend="letref">let</link>.</para></listitem>
linkend="letref">let</link>.</para>
<para><programlisting>n=6/3
echo "n = $n" # n = 6/3
declare -i n
n=6/3
echo "n = $n" # n = 2</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
@ -7726,7 +7847,7 @@ echo "number = $number" # number = 0
</varlistentry>
<varlistentry>
<term>var=$value</term>
<term>-x var=$value</term>
<listitem>
<para><programlisting>declare -x var3=373</programlisting></para>
<para>The <command>declare</command> command permits
@ -7810,14 +7931,11 @@ echo "number = $number" # number = 0
</example>
<note>
<para>
<emphasis>Jipe</emphasis> points out another set of techniques
for generating random numbers within a range.
</para>
<emphasis>Jipe</emphasis> points out a set of techniques for
generating random numbers within a range.
<para>
<programlisting># Generate random number between 6 and 30.
rnumber=$((RANDOM%25+6))
@ -7825,10 +7943,27 @@ rnumber=$((RANDOM%25+6))
#+ but the number must be evenly divisible by 3.
rnumber=$(((RANDOM%30/3+1)*3))
# Note that this will not work all the time.
# It fails if $RANDOM returns 0.
# Exercise: Try to figure out the pattern here.</programlisting>
</para>
</note>
<para>
<emphasis>Bill Gradwohl</emphasis> came up with an improved
formula that works for positive numbers.
<programlisting>rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))</programlisting>
</para>
<para>Here Bill presents a versatile function that returns
a random number between two specified values.</para>
<example id="randombetween">
<title>Random between values</title>
<programlisting>&randombetween;</programlisting>
</example>
<para>Just how random is $RANDOM? The best way to test this is
@ -7837,7 +7972,7 @@ rnumber=$(((RANDOM%30/3+1)*3))
a $RANDOM die a few times...</para>
<example id="randomtest">
<title>Rolling the die with RANDOM</title>
<title>Rolling a single die with RANDOM</title>
<programlisting>&randomtest;</programlisting>
</example>
@ -8888,13 +9023,24 @@ echo; echo "Keypress was "\"$keypress\""."
linkend="echoref">echo</link> to set variables <link
linkend="badread0">will fail</link>.</para>
<para>However, piping the output of <link
linkend="catref">cat</link> does seem to work.
<programlisting>cat file1 file2 |
<para>Yet, piping the output of <link
linkend="catref">cat</link> <emphasis>seems</emphasis> to
work.</para>
<para><programlisting>cat file1 file2 |
while read line
do
echo $line
done</programlisting></para>
<para>However, as Bj&ouml;n Eriksson shows:</para>
<example id="readpipe">
<title>Problems reading from a pipe</title>
<programlisting>&readpipe;</programlisting>
</example>
</note>
@ -9071,7 +9217,7 @@ done</programlisting></para>
complex version of <link linkend="exprref">expr</link>.</para>
<example id="ex46">
<title>Letting <command>let</command> do some arithmetic.</title>
<title>Letting <quote>let</quote> do arithmetic.</title>
<programlisting>&ex46;</programlisting>
</example>
@ -10252,7 +10398,10 @@ wait</programlisting>
<token>>></token>), it is commonly used to concatenate
files.
<programlisting>cat filename cat file.1 file.2 file.3 &gt; file.123</programlisting>
<programlisting># Uses of 'cat'
cat filename # Lists the file.
cat file.1 file.2 file.3 &gt; file.123 # Combines three files into one.</programlisting>
The <option>-n</option> option to <command>cat</command>
inserts consecutive numbers before all lines of the
@ -10418,7 +10567,7 @@ wait</programlisting>
<secondary>mkdir</secondary>
</indexterm>
<listitem>
<para>Make directory, creates a new directory.
<para>Make directory, creates a new directory. For example,
<userinput>mkdir -p project/programs/December</userinput>
creates the named directory. The
<replaceable>-p</replaceable> option automatically creates
@ -10485,13 +10634,24 @@ chmod u+s filename
<term><command>ln</command></term>
<listitem>
<para>Creates links to pre-existings files. Most often used
with the <option>-s</option>, symbolic or
<quote>soft</quote> link flag. This permits referencing
<para>Creates links to pre-existings files. A <quote>link</quote>
is a reference to a file, an alternate name for it.
The <command>ln</command> command permits referencing
the linked file by more than one name and is a superior
alternative to aliasing (see <xref linkend="ex18">).</para>
<para>The <command>ln</command> command is most often used
with the <option>-s</option>, symbolic or
<quote>soft</quote> link flag. Without this flag, the command
actually creates a full-length copy of the file. With it,
<command>ln</command> creates only a reference, a pointer to the
file only a few bytes in size. An additional advantage of
using the <option>-s</option> flag is that it permits linking
across file systems.</para>
<para><userinput>ln -s oldfile newfile</userinput>
<para>The syntax of the command is a bit tricky. For example:
<userinput>ln -s oldfile newfile</userinput>
links the previously existing
<filename>oldfile</filename> to the newly created link,
<filename>newfile</filename>.</para>
@ -11910,7 +12070,7 @@ tr -d 0-9 &lt;filename
</example>
<example id="du">
<title><command>du</command>: DOS to UNIX text file conversion.</title>
<title><command>Du</command>: DOS to UNIX text file conversion.</title>
<programlisting>&du;</programlisting>
</example>
@ -12123,16 +12283,37 @@ tr -d 0-9 &lt;filename
</indexterm>
<indexterm>
<primary>command</primary>
<secondary>gettext</secondary>
<secondary>localization</secondary>
</indexterm>
<listitem>
<para>A GNU utility for <link
linkend="localization">localization</link> and
translating the text output of programs into
foreign languages. While primarily intended for C
programs, <command>gettext</command> also finds
use in shell scripts. See the <replaceable>info
page</replaceable>.</para>
<para>The GNU <command>gettext</command> package is a set of
utilities for <link linkend="localization">localizing</link>
and translating the text output of programs into foreign
languages. While originally intended for C programs, it
now supports quite a number of programming and scripting
languages.</para>
<para>The <command>gettext</command>
<emphasis>program</emphasis> works on shell scripts. See
the <replaceable>info page</replaceable>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><anchor id="msgfmtref"><command>msgfmt</command></term>
<indexterm>
<primary>msgfmt</primary>
</indexterm>
<indexterm>
<primary>command</primary>
<secondary>localization</secondary>
</indexterm>
<listitem>
<para>A program for generating binary
message catalogs. It is used for <link
linkend="localization">localization</link>.</para>
</listitem>
</varlistentry>
@ -12147,7 +12328,8 @@ tr -d 0-9 &lt;filename
</indexterm>
<listitem>
<para>A utility for converting file(s) to a different encoding
(character set). Its chief use is for localization.</para>
(character set). Its chief use is for <link
linkend="localization">localization</link>.</para>
</listitem>
</varlistentry>
@ -14609,7 +14791,9 @@ LIMIT_STRING
parses command-line options preceded by a <link
linkend="dashref">dash</link>. This external command
corresponds to the <link linkend="getoptsx">getopts</link>
Bash builtin, but it is not nearly as versatile.</para>
Bash builtin, but it is not nearly as versatile. However,
<command>getopt</command> does permit handling long options
by use of the <option>-l</option> flag.</para>
<example id="ex33a">
<title>Using <command>getopt</command> to parse command-line
@ -16409,16 +16593,21 @@ exit 0
<screen>
<prompt>bash$ </prompt><userinput>sar</userinput>
<computeroutput>Linux 2.4.7-10 (localhost.localdomain) 12/31/2001
<computeroutput>Linux 2.4.9 (brooks.seringas.fr) 09/26/03
10:30:01 AM CPU %user %nice %system %idle
10:40:00 AM all 1.39 0.00 0.77 97.84
10:50:00 AM all 76.83 0.00 1.45 21.72
11:00:00 AM all 1.32 0.00 0.69 97.99
11:10:00 AM all 1.17 0.00 0.30 98.53
11:20:00 AM all 0.51 0.00 0.30 99.19
06:30:00 PM all 100.00 0.00 100.01 0.00
Average: all 1.39 0.00 0.66 97.95</computeroutput>
10:30:00 CPU %user %nice %system %iowait %idle
10:40:00 all 2.21 10.90 65.48 0.00 21.41
10:50:00 all 3.36 0.00 72.36 0.00 24.28
11:00:00 all 1.12 0.00 80.77 0.00 18.11
Average: all 2.23 3.63 72.87 0.00 21.27
14:32:30 LINUX RESTART
15:00:00 CPU %user %nice %system %iowait %idle
15:10:00 all 8.59 2.40 17.47 0.00 71.54
15:20:00 all 4.07 1.00 11.95 0.00 82.98
15:30:00 all 0.79 2.94 7.56 0.00 88.71
Average: all 6.33 1.70 14.71 0.00 77.26</computeroutput>
</screen>
</listitem>
</varlistentry>
@ -19733,7 +19922,9 @@ COMMAND7</programlisting>
<programlisting>if (set -u; : $variable) 2&gt; /dev/null
then
echo "Variable is set."
fi
fi # Variable has been set in current script,
#+ or is an an internal Bash variable,
#+ or is present in environment (has been exported).
# Could also be written [[ ${variable-x} != x || ${variable-y} != y ]]
# or [[ ${variable-x} != x$variable ]]
@ -20472,6 +20663,9 @@ echo "global_var = $global_var" # global_var = 37
script with a segfault.
<programlisting>#!/bin/bash
# Warning: Running this script could possibly lock up your system!
# If you're lucky, it will segfault before using up all available memory.
recursive_function ()
{
(( $1 < $2 )) && f $(( $1 + 1 )) $2;
@ -20480,14 +20674,16 @@ recursive_function ()
}
recursive_function 1 50000 # Recurse 50,000 levels!
# Segfaults, of course.
# Most likely segfaults (depending on stack size, set by ulimit -m).
# Recursion this deep might cause even a C program to segfault,
#+ by using up all the memory allotted to the stack.
# Thanks, S.C.
exit 0 # This script will not exit normally.</programlisting>
echo "This will probably not print."
exit 0 # This script will not exit normally.
# Thanks, Stephane Chazelas.</programlisting>
</para></footnote>
</para>
@ -20754,30 +20950,20 @@ echo ${#string[@]} # 1
standard Bash commands and operators have special options adapted
for array use.</para>
<para>
<programlisting>array=( zero one two three four five )
<example id="arrayops">
<title>Various array operations</title>
<programlisting>&arrayops;</programlisting>
</example>
echo ${array[0]} # zero
echo ${array:0} # zero
# Parameter expansion of first element.
echo ${array:1} # ero
# Parameter expansion of first element,
#+ starting at position #1 (2nd character).
<para>Many of the standard <link linkend="stringmanip">string
operations</link> work on arrays.</para>
echo ${#array} # 4
# Length of first element of array.
<example id="arraystrops">
<title>String operations on arrays</title>
<programlisting>&arraystrops;</programlisting>
</example>
array2=( [0]="first element" [1]="second element" [3]="fourth element" )
echo ${array2[0]} # first element
echo ${array2[1]} # second element
echo ${array2[2]} #
# Skipped in initialization, therefore null.
echo ${array2[3]} # fourth element</programlisting>
</para>
<para><link linkend="commandsubref">Command substitution</link> can
construct the individual elements of an array.</para>
@ -20869,11 +21055,22 @@ echo $element_count # 8</programlisting>
<para>Clever scripting makes it possible to add array operations.</para>
<example id="arrayassign">
<title>Initializing arrays</title>
<programlisting>&arrayassign;</programlisting>
</example>
<example id="copyarray">
<title>Copying and concatenating arrays</title>
<programlisting>&copyarray;</programlisting>
</example>
<example id="arrayappend">
<title>More on concatenating arrays</title>
<programlisting>&arrayappend;</programlisting>
</example>
<para>--</para>
<para>Arrays permit deploying old familiar algorithms as shell scripts.
@ -22046,7 +22243,7 @@ exit 0</programlisting>
<para><anchor id="badread0"></para>
<para><link linkend="piperef">Piping</link>
<command>echo</command>output to a <link
<command>echo</command> output to a <link
linkend="readref">read</link> may produce unexpected
results. In this scenario, the <command>read</command>
acts as if it were running in a subshell. Instead, use
@ -23385,7 +23582,7 @@ fi</programlisting>
<para>The current version of <emphasis>Bash</emphasis>, the one
you have running on your machine, is actually version 2.XX.Y.
<screen><prompt>bash$ </prompt><userinput>echo $BASH_VERSION</userinput>
<computeroutput>2.05.8(1)-release</computeroutput>
<computeroutput>2.05.b.0(1)-release</computeroutput>
</screen>
This update of the classic Bash scripting language added array
variables,
@ -23487,7 +23684,7 @@ fi</programlisting>
mortgage calculator, the <ulink
url="http://ibiblio.org/pub/Linux/games/amusements/judge-1.0.tar.gz">judge</ulink>
Scrabble&reg; adjudicator, and the <ulink
url="http://ibiblio.org/pub/Linux/libs/yawl-0.2.tar.gz">yawl</ulink>
url="http://ibiblio.org/pub/Linux/libs/yawl-0.3.tar.gz">yawl</ulink>
word gaming list package. He got his start in programming using
FORTRAN IV on a CDC 3800, but is not the least bit nostalgic
for those days.</para>
@ -23498,6 +23695,22 @@ fi</programlisting>
</sect1> <!-- About the Author -->
<sect1 id="wherehelp">
<title>Where to Go For Help</title>
<para><ulink url="mailto:thegrendel@theriver.com">The author</ulink>
will usually, if not too busy (and in a good mood),
answer general scripting questions. However, if
you have a problem getting a specific script to
work, you would be well advised to post to the <ulink
url="news:comp.unix.shell">comp.os.unix.shell</ulink> Usenet
newsgroup.</para>
</sect1> <!-- Where to Go For Help -->
<sect1 id="toolsused">
<title>Tools Used to Produce This Book</title>
@ -23646,11 +23859,12 @@ fi</programlisting>
were Gabor Kiss, Leopold Toetsch, Peter Tillier, Marcus Berglof,
Tony Richardson, Nick Drage (script ideas!), Rich Bartell, Jess
Thrysoee, Adam Lazur, Bram Moolenaar, Baris Cicek, Greg Keraunen,
Keith Matthews, Sandro Magi, Albert Reiner, Dim Segebart, Rory
Winston, Lee Bigelow, Wayne Pollock, <quote>jipe,</quote> Emilio
Conti, Dennis Leeuw, Dan Jacobson, Aurelio Marinho Jargas,
Edward Scholtz, Jean Helou, Chris Martin, and David Lawyer
(himself an author of 4 HOWTOs).</para>
Keith Matthews, Sandro Magi, Albert Reiner, Dim Segebart,
Rory Winston, Lee Bigelow, Wayne Pollock, <quote>jipe,</quote>
Emilio Conti, Dennis Leeuw, Dan Jacobson, Aurelio Marinho Jargas,
Edward Scholtz, Jean Helou, Chris Martin, Lee Maschmeyer, Bruno
Haible, Sebastien Godard, Bj&ouml;n Eriksson, Bill Gradwohl,
and David Lawyer (himself an author of four HOWTOs).</para>
<para>My gratitude to <ulink url="mailto:chet@po.cwru.edu">Chet
Ramey</ulink> and Brian Fox for writing <command>Bash</command>,
@ -23917,6 +24131,27 @@ fi</programlisting>
</abstract>
</biblioentry>
<biblioentry>
<authorgroup>
<author><firstname>Chet</firstname><surname>Ramey</surname></author>
<author><firstname>Brian</firstname><surname>Fox</surname></author>
</authorgroup>
<title><ulink
url="http://www.network-theory.co.uk/bash/manual/">The GNU Bash Reference Manual</ulink></title>
<publisher>
<publishername>Network Theory Ltd</publishername>
</publisher>
<copyright>
<year>2003</year>
</copyright>
<isbn>0-9541617-7-7</isbn>
<abstract><para>This manual is the definitive reference for
GNU Bash. The authors of this manual, Chet Ramey and Brian Fox,
are the original developers of GNU Bash. For each copy sold the
publisher donates $1 to the Free Software Foundation.</para>
</abstract>
</biblioentry>
<biblioentry>
<authorgroup>
<author><firstname>Arnold</firstname><surname>Robbins</surname></author>
@ -24223,6 +24458,15 @@ fi</programlisting>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para><ulink url="mailto:brtompkins@comcast.net">Ben
Tomkins</ulink> has created the <ulink
url="http://bashnavigator.sourceforge.net">
Bash Navigator</ulink> directory management tool.</para>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para>Rocky Bernstein is in the process of developing a
@ -24435,6 +24679,30 @@ fi</programlisting>
<programlisting>&objoriented;</programlisting>
</example>
<para>How do you keep the shell from expanding and reinterpreting
strings?</para>
<example id="protectliteral">
<title>Protecting literal strings</title>
<programlisting>&protectliteral;</programlisting>
</example>
<para>What if you <emphasis>want</emphasis> the shell to expand
and reinterpret strings?</para>
<example id="unprotectliteral">
<title>Unprotecting literal strings</title>
<programlisting>&unprotectliteral;</programlisting>
</example>
<para>To end this section, a review of the basics . . . and more.</para>
<example id="basicsreviewed">
<title>Basics Reviewed</title>
<programlisting>&basicsreviewed;</programlisting>
</example>
</appendix>
<!-- End Contributed Scripts appendix -->
@ -25421,7 +25689,15 @@ awk '{print $1 $5 $6}' $filename
<command>BEGIN</command>, for a code block to be performed before awk
starts processing its input.</para>
<para>For examples of awk within shell scripts, see:
<para>The following example illustrates how <command>awk</command> can
add text-parsing tools to a shell script.</para>
<example id="lettercount">
<title>Counting Letter Occurrences</title>
<programlisting>&lettercount;</programlisting>
</example>
<para>For simpler examples of awk within shell scripts, see:
<orderedlist>
<listitem><para><xref linkend="ex44"></para></listitem>
<listitem><para><xref linkend="redir4"></para></listitem>
@ -25708,6 +25984,7 @@ exit 0</programlisting>
<appendix id="localization">
<title>Localization</title>
<para>Localization is an undocumented Bash feature.</para>
<para>A localized shell script echoes its text output in the
@ -25723,6 +26000,9 @@ exit 0</programlisting>
<para>
<programlisting>#!/bin/bash
# localized.sh
# Script by Stephane Chazelas, modified by Bruno Haible
. gettext.sh
E_CDERROR=65
@ -25732,8 +26012,8 @@ error()
exit $E_CDERROR
}
cd $var || error $"Can't cd to %s." "$var"
read -p $"Enter the value: " var
cd $var || error "`eval_gettext \"Can't cd to \$var.\"`"
read -p "`gettext \"Enter the value: \"`" var
# ...</programlisting>
</para>
@ -25762,6 +26042,25 @@ read -p $"Enter the value: " var
</para>
<note>
<para>Bruno Haible points out:</para>
<para>Starting with gettext-0.12.2, <command>xgettext -o - localized.sh</command>
is recommended instead of <command>bash --dump-po-strings
localized.sh</command>, because <command>xgettext</command> . . .</para>
<para>1. understands the gettext and eval_gettext commands
(whereas bash --dump-po-strings understands only its deprecated
$"..." syntax)</para>
<para>2. can extract comments placed by the programmer, intended
to be read by the translator.</para>
<para>This shell code is then not specific to Bash any
more; it works the same way with Bash 1.x and other /bin/sh
implementations.</para>
</note>
<para>Now, build a <filename>language.po</filename>
file for each language that the script will be translated
@ -25778,7 +26077,7 @@ msgid "Enter the value: "
msgstr "Entrez la valeur : "</programlisting>
</para>
<para>Then, run <command>msgfmt</command>.</para>
<para>Then, run <link linkend="msgfmtref">msgfmt</link>.</para>
<para><userinput>msgfmt -o localized.sh.mo fr.po</userinput></para>
<para>Place the resulting <filename>localized.sh.mo</filename> file in the
@ -25821,7 +26120,9 @@ read -p "$(gettext -s "Enter the value: ")" var
<para>---</para>
<para>This appendix written by Stephane Chazelas.</para>
<para>This appendix written by Stephane Chazelas, with modifications
suggested by Bruno Haible, maintainer of GNU
<link linkend="gettextref">gettext</link>.</para>
</appendix>
<!-- Localization -->
@ -26698,7 +26999,7 @@ Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612
</varlistentry>
<varlistentry>
<term><command>Passwords</command></term>
<term><command>Generating Passwords</command></term>
<listitem>
<para>Generate pseudorandom 8-character passwords, using
characters in the ranges [0-9], [A-Z], [a-z]. Each password
@ -26712,6 +27013,59 @@ Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612
<variablelist id="exdifficult">
<title><anchor id="exdifficult1">Difficult</title>
<varlistentry>
<term><command>Testing Passwords</command></term>
<listitem>
<para>Write a script to check and validate passwords. The object
is to flag <quote>weak</quote> or easily guessed password
candidates.</para>
<para>A trial password will be input to the script as a
command line parameter. To be considered acceptable,
a password must meet the following minimum qualifications:
<itemizedlist>
<listitem>
<para>Minimum length of 8 characters</para>
</listitem>
<listitem>
<para>Must contain at least one numeric character</para>
</listitem>
<listitem>
<para>Must contain at least one of the following
non-alphabetic characters: <token>@</token>,
<token>#</token>, <token>$</token>, <token>%</token>,
<token>&</token>, <token>*</token>, <token>+</token>,
<token>-</token>, <token>=</token></para>
</listitem>
</itemizedlist></para>
<para>Optional:
<itemizedlist>
<listitem>
<para>Do a dictionary check on every sequence of at least
four consecutive alphabetic characters in the password under
test. This will eliminate passwords containing embedded
<quote>words</quote> found in a standard dictionary.</para>
</listitem>
<listitem>
<para>Enable the script to check all the passwords on your
system. These may or may not reside in
<filename>/etc/passwd</filename>.</para>
</listitem>
</itemizedlist></para>
<para>This exercise tests mastery of <link
linkend="regexref">Regular Expressions</link>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>Logging File Accesses</command></term>
<listitem>
@ -27060,11 +27414,14 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
<appendix id="copyright">
<title>Copyright</title>
<para>The <quote>Advanced Bash-Scripting Guide</quote> is <trademark
<para>The <quote>Advanced Bash Scripting Guide</quote> is <trademark
class=copyright>copyright </trademark> 2000, by Mendel Cooper. The
author also asserts copyright on all previous versions of this
document.</para>
<para>This blanket copyright recognizes and protects the rights of the
contributors to this document.</para>
<para>This document may only be distributed subject to the terms
and conditions set forth in the Open Publication
@ -27149,10 +27506,11 @@ B. Distribution of the work or derivative of the work in any standard
<para>Hyun Jin Cha has done a <ulink
url="http://kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html">Korean
translation</ulink> of version 1.0.11 of this book. Spanish,
Portuguese, French, German, Italian, and Chinese translations
are underway. If you wish to translate this document into another
language, please feel free to do so, subject to the terms stated
above. The author wishes to be notified of such efforts.</para>
Portuguese, French, German, Italian, Russian, and Chinese
translations are also available or in progress. If you wish to
translate this document into another language, please feel free
to do so, subject to the terms stated above. The author wishes to
be notified of such efforts.</para>
</appendix> <!-- End Copyright appendix -->

View File

@ -3,7 +3,7 @@
# Adding a second hard drive to system.
# Software configuration. Assumes hardware already mounted.
# From an article by the author of this document.
# in issue #38 of "Linux Gazette", http://www.linuxgazette.com.
# In issue #38 of "Linux Gazette", http://www.linuxgazette.com.
ROOT_UID=0 # This script must be run as root.
E_NOTROOT=67 # Non-root exit error.

View File

@ -9,10 +9,11 @@ grep '.......' | # With at least 7 letters,
grep '^is' | # starting with 'is'
grep -v 's$' | # no plurals
grep -v 'ed$' # no past tense verbs
# Possible to add many combinations of conditions.
# Uses "anagram" utility
#+ that is part of the author's "yawl" word list package.
# http://ibiblio.org/pub/Linux/libs/yawl-0.2.tar.gz
# http://ibiblio.org/pub/Linux/libs/yawl-0.3.tar.gz
exit 0 # End of code.

View File

@ -12,7 +12,7 @@ fi
echo
index=1
index=1 # Initialize count.
echo "Listing args with \"\$*\":"
for arg in "$*" # Doesn't work properly if "$*" isn't quoted.
@ -24,7 +24,8 @@ echo "Entire arg list seen as single word."
echo
index=1
index=1 # Reset count.
# What happens if you forget to do this?
echo "Listing args with \"\$@\":"
for arg in "$@"
@ -36,6 +37,8 @@ echo "Arg list seen as separate words."
echo
index=1 # Reset count.
echo "Listing args with \$* (unquoted):"
for arg in $*
do

View File

@ -11,27 +11,28 @@
# The plot is actually all water, except for the four corners.
# (Think of it as a square with an inscribed circle.)
#
# Let us fire solid iron cannonballs from an old-style cannon
# Let us fire iron cannonballs from an old-style cannon
#+ at the square of land.
# All the shots impact somewhere on the plot of land,
#+ either in the lake or on the dry corners.
# Since the lake takes up most of the land area,
#+ most of the shots will SPLASH! into the water.
# Just a few shots will THUD! into solid ground
#+ in the far corners of the land.
#+ in the four corners of the land.
#
# If we take enough random, unaimed shots at the plot of land,
#+ Then the ratio of SPLASHES to total shots will approximate
#+ the value of PI/4.
#
# The reason for this is that the cannon is actually shooting
#+ only at the upper right-hand quadrant of the square.
#+ only at the upper right-hand quadrant of the square,
#+ i.e., Quadrant I of the Cartesian coordinate plane.
# (The previous explanation was a simplification.)
#
# Theoretically, the more shots taken, the better the fit.
# However, a shell script, as opposed to a compiled language
#+ with floating-point math built in, requires a few compromises.
# This tends to make the simulation less accurate, unfortunately.
# This tends to lower the accuracy of the simulation, unfortunately.
DIMENSION=10000 # Length of each side of the plot of land.
@ -86,6 +87,7 @@ do
printf "Yc = %4d " $yCoord
printf "Distance = %5d " $distance # Distance from
#+ center of lake,
# the "origin,"
#+ coordinate (0,0).
if [ "$distance" -le "$DIMENSION" ]
@ -106,7 +108,7 @@ done
echo
echo "After $shots shots, PI looks like approximately $Pi."
# Tends to run a bit high...
# Tends to run a bit high . . .
# Probably due to round-off error and imperfect randomness of $RANDOM.
echo

View File

@ -8,7 +8,7 @@
# Thank you, all you good people at LJ.
#Input error in dialog box.
# Input error in dialog box.
E_INPUT=65
# Dimensions of display, input widgets.
HEIGHT=50

View File

@ -2,9 +2,9 @@
# Example "ex72.sh" modified to use encrypted password.
# Note that this is still somewhat insecure,
# Note that this is still rather insecure,
#+ since the decrypted password is sent in the clear.
# Use something like "ssh" if this is a concern.
# Use something like "ssh" if this is a concern.
E_BADARGS=65

View File

@ -4,7 +4,7 @@
echo -n "What is your name? "
read name # Try to backspace
#+ to erase characters of input.
# Won't work.
# Problems?
echo "Your name is $name."
stty erase '#' # Set "hashmark" (#) as erase character.
@ -12,4 +12,6 @@ echo -n "What is your name? "
read name # Use # to erase last character typed.
echo "Your name is $name."
# Warning: Even after the script exits, the new key value remains set.
exit 0

View File

@ -1,6 +1,7 @@
#!/bin/bash
# Invoke both with and without arguments, and see what happens.
# Invoke this script both with and without arguments,
#+ and see what happens.
for a
do

View File

@ -10,7 +10,7 @@ do
echo "Your favorite veggie is $vegetable."
echo "Yuck!"
echo
break # if no 'break' here, keeps looping forever.
break # What happens if there is no 'break' here?
done
exit 0

View File

@ -1,6 +1,9 @@
#!/bin/bash
# Exercising getopts and OPTIND
# Script modified 10/09/03 at the suggestion of Bill Gradwohl.
# 'getopts' processes command line arguments to script.
# Here we observe how 'getopts' processes command line arguments to script.
# The arguments are parsed as "options" (flags) and associated arguments.
# Try invoking this script with
@ -10,8 +13,11 @@
#
# 'scriptname -qr' - Unexpected result, takes "r" as the argument to option "q"
# 'scriptname -q -r' - Unexpected result, same as above
# 'scriptname -mnop -mnop' - Unexpected result
# (OPTIND is unreliable at stating where an option came from).
#
# If an option expects an argument ("flag:"), then it will grab
# whatever is next on the command line.
#+ whatever is next on the command line.
NO_ARGS=0
E_OPTERROR=65
@ -28,18 +34,26 @@ fi
while getopts ":mnopq:rs" Option
do
case $Option in
m ) echo "Scenario #1: option -m-";;
n | o ) echo "Scenario #2: option -$Option-";;
p ) echo "Scenario #3: option -p-";;
q ) echo "Scenario #4: option -q-, with argument \"$OPTARG\"";;
# Note that option 'q' must have an associated argument,
# otherwise it falls through to the default.
r | s ) echo "Scenario #5: option -$Option-"'';;
m ) echo "Scenario #1: option -m- [OPTIND=${OPTIND}]";;
n | o ) echo "Scenario #2: option -$Option- [OPTIND=${OPTIND}]";;
p ) echo "Scenario #3: option -p- [OPTIND=${OPTIND}]";;
q ) echo "Scenario #4: option -q-\
with argument \"$OPTARG\" [OPTIND=${OPTIND}]";;
# Note that option 'q' must have an associated argument,
#+ otherwise it falls through to the default.
r | s ) echo "Scenario #5: option -$Option-";;
* ) echo "Unimplemented option chosen.";; # DEFAULT
esac
done
shift $(($OPTIND - 1))
# Decrements the argument pointer so it points to next argument.
# Decrements the argument pointer so it points to next argument.
# $1 now references the first non option item supplied on the command line
#+ if one exists.
exit 0
# As Bill Gradwohl states,
# "The getopts mechanism allows one to specify: scriptname -mnop -mnop
#+ but there is no reliable way to differentiate what came from where
#+ by using OPTIND."

View File

@ -1,16 +1,17 @@
#!/bin/bash
# Using getopt.
# Try the following when invoking this script.
# sh ex33a -a
# sh ex33a -abc
# sh ex33a -a -b -c
# sh ex33a -d
# sh ex33a -dXYZ
# sh ex33a -d XYZ
# sh ex33a -abcd
# sh ex33a -abcdZ
# sh ex33a -z
# sh ex33a a
# Try the following when invoking this script:
# sh ex33a.sh -a
# sh ex33a.sh -abc
# sh ex33a.sh -a -b -c
# sh ex33a.sh -d
# sh ex33a.sh -dXYZ
# sh ex33a.sh -d XYZ
# sh ex33a.sh -abcd
# sh ex33a.sh -abcdZ
# sh ex33a.sh -z
# sh ex33a.sh a
# Explain the results of each of the above.
E_OPTERR=65
@ -38,7 +39,7 @@ do
shift
done
# It is better to use the 'getopts' builtin in a script,
# It is usually better to use the 'getopts' builtin in a script,
#+ rather than 'getopt'.
# See "ex33.sh".

View File

@ -1,12 +1,14 @@
#!/bin/bash
# Copy (verbose) all files in current directory
# to directory specified on command line.
# Copy (verbose) all files in current directory
#+ to directory specified on command line.
E_NOARGS=65
if [ -z "$1" ] # Exit if no argument given.
then
echo "Usage: `basename $0` directory-to-copy-to"
exit 65
exit $E_NOARGS
fi
ls . | xargs -i -t cp ./{} $1

View File

@ -2,25 +2,27 @@
echo
let a=11 # Same as 'a=11'
let a=a+5 # Equivalent to let "a = a + 5"
# (double quotes and spaces make it more readable)
echo "11 + 5 = $a"
let a=11 # Same as 'a=11'
let a=a+5 # Equivalent to let "a = a + 5"
# (Double quotes and spaces make it more readable.)
echo "11 + 5 = $a" # 16
let "a <<= 3" # Equivalent to let "a = a << 3"
let "a <<= 3" # Equivalent to let "a = a << 3"
echo "\"\$a\" (=16) left-shifted 3 places = $a"
# 128
let "a /= 4" # Equivalent to let "a = a / 4"
echo "128 / 4 = $a"
let "a /= 4" # Equivalent to let "a = a / 4"
echo "128 / 4 = $a" # 32
let "a -= 5" # Equivalent to let "a = a - 5"
echo "32 - 5 = $a"
let "a -= 5" # Equivalent to let "a = a - 5"
echo "32 - 5 = $a" # 27
let "a = a * 10" # Equivalent to let "a = a * 10"
echo "27 * 10 = $a"
let "a *= 10" # Equivalent to let "a = a * 10"
echo "27 * 10 = $a" # 270
let "a %= 8" # Equivalent to let "a = a % 8"
let "a %= 8" # Equivalent to let "a = a % 8"
echo "270 modulo 8 = $a (270 / 8 = 33, remainder $a)"
# 6
echo

View File

@ -1,6 +1,6 @@
#!/bin/bash
# Copying a directory tree using cpio.
# Copying a directory tree using 'cpio.'
ARGS=2
E_BADARGS=65
@ -15,6 +15,10 @@ source=$1
destination=$2
find "$source" -depth | cpio -admvp "$destination"
# Read the man page to decipher these cpio options.
# ^^^^^ ^^^^^
# Read the 'find' and 'cpio' man page to decipher these options.
# It may be useful to check the exit status ($?) here
#+ to see if everything worked all right.
exit 0

View File

@ -7,6 +7,6 @@ b=`ls /usr/local/bin` # Get a file listing...
echo $b | fmt -w $WIDTH
# Could also have been done by
# echo $b | fold - -s -w $WIDTH
# echo $b | fold - -s -w $WIDTH
exit 0

View File

@ -1,25 +1,29 @@
#!/bin/bash
# Global and local variables inside a function.
func ()
{
local loc_var=23 # Declared local.
echo
local loc_var=23 # Declared as local variable.
echo # Uses the 'local' builtin.
echo "\"loc_var\" in function = $loc_var"
global_var=999 # Not declared local.
global_var=999 # Not declared as local.
# Defaults to global.
echo "\"global_var\" in function = $global_var"
}
func
# Now, see if local 'a' exists outside function.
# Now, to see if local variable "loc_var" exists outside function.
echo
echo "\"loc_var\" outside function = $loc_var"
# "loc_var" outside function =
# Nope, $loc_var not visible globally.
# $loc_var outside function =
# No, $loc_var not visible globally.
echo "\"global_var\" outside function = $global_var"
# "global_var" outside function = 999
# $global_var outside function = 999
# $global_var is visible globally.
echo
exit 0
# In contrast to C, a Bash variable declared inside a function
#+ is local *only* if declared as such.

View File

@ -1,14 +1,17 @@
#!/bin/bash
# upload.sh
# Upload file pair (Filename.lsm, Filename.tar.gz)
# to incoming directory at Sunsite (ibiblio.org).
# Upload file pair (Filename.lsm, Filename.tar.gz)
#+ to incoming directory at Sunsite/UNC (ibiblio.org).
# Filename.tar.gz is the tarball itself.
# Filename.lsm is the descriptor file.
E_ARGERROR=65
if [ -z "$1" ]
then
echo "Usage: `basename $0` filename"
echo "Usage: `basename $0` Filename-to-upload"
exit $E_ARGERROR
fi
@ -17,8 +20,8 @@ Filename=`basename $1` # Strips pathname out of file name.
Server="ibiblio.org"
Directory="/incoming/Linux"
# These need not be hard-coded into script,
# but may instead be changed to command line argument.
# These need not be hard-coded into script,
#+ but may instead be changed to command line argument.
Password="your.e-mail.address" # Change above to suit.

View File

@ -2,6 +2,7 @@
# ex74.sh
# This is a buggy script.
# Where, oh where is the error?
a=37

View File

@ -1,8 +1,9 @@
#!/bin/bash
# This is supposed to delete all filenames in current directory
# This script is supposed to delete all filenames in current directory
#+ containing embedded spaces.
# It doesn't work. Why not?
# It doesn't work.
# Why not?
badname=`ls | grep ' '`

View File

@ -1,4 +1,5 @@
#!/bin/bash
# Hunting variables with a trap.
trap 'echo Variable Listing --- a = $a b = $b' EXIT
# EXIT is the name of the signal generated upon exit from a script.

View File

@ -3,11 +3,14 @@
# String expansion.
# Introduced with version 2 of Bash.
# Strings of the form $'xxx'
# have the standard escaped characters interpreted.
# Strings of the form $'xxx'
#+ have the standard escaped characters interpreted.
echo $'Ringing bell 3 times \a \a \a'
# May only ring once with certain terminals.
echo $'Three form feeds \f \f \f'
echo $'10 newlines \n\n\n\n\n\n\n\n\n\n'
echo $'\102\141\163\150' # Bash
# Octal equivalent of characters.
exit 0

View File

@ -14,3 +14,4 @@ cat -n `basename $0`
# Note that 'nl -ba' will also do so.
exit 0
# -----------------------------------------------------------------

View File

@ -27,7 +27,7 @@ FD_DEBUG3=5
log() # Writes time and date to log file.
{
echo "$(date) $*" &gt;&7 # This *appends* the date to the file.
# See below.
# See below.
}

View File

@ -1,8 +1,9 @@
#!/bin/bash
# manview.sh: Formats the source of a man page for viewing.
# This is useful when writing man page source and you want to
#+ look at the intermediate results on the fly while working on it.
# This script is useful when writing man page source.
# It lets you look at the intermediate results on the fly
#+ while working on it.
E_WRONGARGS=65
@ -12,8 +13,10 @@ then
exit $E_WRONGARGS
fi
# ---------------------------
groff -Tascii -man $1 | less
# From the man page for groff.
# ---------------------------
# If the man page includes tables and/or equations,
#+ then the above code will barf.

View File

@ -1,4 +1,6 @@
#!/bin/bash
# patt-matching.sh
# Pattern matching using the # ## % %% parameter substitution operators.
var1=abcd12345abc6789
@ -6,7 +8,8 @@ pattern1=a*c # * (wild card) matches everything between a - c.
echo
echo "var1 = $var1" # abcd12345abc6789
echo "var1 = ${var1}" # abcd12345abc6789 (alternate form)
echo "var1 = ${var1}" # abcd12345abc6789
# (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo "pattern1 = $pattern1" # a*c (everything between 'a' and 'c')
echo
@ -33,7 +36,7 @@ echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a
# Longest possible match, strips out last 12 characters abcd12345abc6789
# ^^^^ |-------------|
# Remember, # and ## work from the left end of string,
# Remember, # and ## work from the left end (beginning) of string,
# % and %% work from the right end.
echo

View File

@ -6,6 +6,7 @@
MINARGS=1 # Script needs at least one argument.
DATAFILE=./phonebook
# A data file named "phonebook" must exist.
PROGNAME=$0
E_NOARGS=70 # No arguments error.
@ -17,6 +18,7 @@ fi
if [ $# -eq $MINARGS ]; then
grep $1 "$DATAFILE"
# 'grep' prints an error message if $DATAFILE not present.
else
( shift; "$PROGNAME" $* ) | grep $1
# Script recursively calls itself.
@ -44,4 +46,4 @@ $bash pb.sh Roe Sam
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678
# When more than one argument passed to script,
#+ prints *only* the line(s) containing all the arguments.
#+ it prints *only* the line(s) containing all the arguments.

View File

@ -11,7 +11,7 @@ Line[5]="Or just after."
# Attribution.
Attrib[1]=" Wallace Stevens"
Attrib[2]="\"Thirteen Ways of Looking at a Blackbird\""
# Above poem is in the Public Domain (copyright expired).
# This poem is in the Public Domain (copyright expired).
for index in 1 2 3 4 5 # Five lines.
do

View File

@ -37,9 +37,9 @@ Primes 1
exit 0
# Uncomment lines 17 and 25 to help figure out what is going on.
# Uncomment lines 16 and 24 to help figure out what is going on.
# Compare the speed of this algorithm for generating primes
# with the Sieve of Eratosthenes (ex68.sh).
# Compare the speed of this algorithm for generating primes
#+ with the Sieve of Eratosthenes (ex68.sh).
# Exercise: Rewrite this script without recursion, for faster execution.
# Exercise: Rewrite this script without recursion, for faster execution.

View File

@ -3,11 +3,14 @@
# Uses the awk rand() function.
AWKSCRIPT=' { srand(); print rand() } '
# Command(s) / parameters passed to awk
# Command(s) / parameters passed to awk
# Note that srand() reseeds awk's random number generator.
echo -n "Random number between 0 and 1 = "
echo | awk "$AWKSCRIPT"
# What happens if you leave out the 'echo'?
exit 0
@ -17,9 +20,9 @@ exit 0
# 1) Using a loop construct, print out 10 different random numbers.
# (Hint: you must reseed the "srand()" function with a different seed
# in each pass through the loop. What happens if you fail to do this?)
#+ in each pass through the loop. What happens if you fail to do this?)
# 2) Using an integer multiplier as a scaling factor, generate random numbers
# in the range between 10 and 100.
#+ in the range between 10 and 100.
# 3) Same as exercise #2, above, but generate random integers this time.

View File

@ -9,7 +9,7 @@ RANGE=10
MAXVAL=9
i=$RANDOM
let "i %= $RANGE" # Generate a random number between 0 and $MAXVAL.
let "i %= $RANGE" # Generate a random number between 0 and $RANGE - 1.
if [ "$i" -lt "$MAXVAL" ]
then

View File

@ -1,4 +1,7 @@
#!/bin/bash
# reply.sh
# REPLY is the default value for a 'read' command.
echo
echo -n "What is your favorite vegetable? "

View File

@ -1,6 +1,6 @@
#!/bin/bash
# str-test.sh: Testing null strings and unquoted strings,
# but not strings and sealing wax, not to mention cabbages and kings...
# str-test.sh: Testing null strings and unquoted strings,
#+ but not strings and sealing wax, not to mention cabbages and kings . . .
# Using if [ ... ]
@ -28,7 +28,7 @@ then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi # Quote strings within test brackets!
fi # Quote strings within test brackets!
echo
@ -45,8 +45,8 @@ fi
# However it is good practice to quote it ("$string1").
#
# As Stephane Chazelas points out,
# if [ $string 1 ] has one argument, "]"
# if [ "$string 1" ] has two arguments, the empty "$string1" and "]"
# if [ $string1 ] has one argument, "]"
# if [ "$string1" ] has two arguments, the empty "$string1" and "]"
@ -63,7 +63,7 @@ else
echo "String \"string1\" is null."
fi
# Again, gives correct result.
# Still, it is better to quote it ("$string1"), because...
# Still, it is better to quote it ("$string1"), because . . .
string1="a = b"
@ -77,4 +77,4 @@ fi
# Not quoting "$string1" now gives wrong result!
exit 0
# Also, thank you, Florian Wisser, for the "heads-up".
# Thank you, also, Florian Wisser, for the "heads-up".

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Simulating a two-dimensional array.
# twodim.sh: Simulating a two-dimensional array.
# A two-dimensional array stores rows sequentially.
@ -7,7 +7,7 @@ Rows=5
Columns=5
declare -a alpha # char alpha [Rows] [Columns];
# Unnecessary declaration.
# Unnecessary declaration. Why?
load_alpha ()
{
@ -16,17 +16,18 @@ local index
for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y
do
do # Use different symbols if you like.
local row=`expr $rc / $Columns`
local column=`expr $rc % $Rows`
let "index = $row * $Rows + $column"
alpha[$index]=$i # alpha[$row][$column]
alpha[$index]=$i
# alpha[$row][$column]
let "rc += 1"
done
# Simpler would be
# declare -a alpha=( A B C D E F G H I J K L M N O P Q R S T U V W X Y )
# but this somehow lacks the "flavor" of a two-dimensional array.
# Simpler would be
#+ declare -a alpha=( A B C D E F G H I J K L M N O P Q R S T U V W X Y )
#+ but this somehow lacks the "flavor" of a two-dimensional array.
}
print_alpha ()
@ -63,12 +64,14 @@ filter () # Filter out negative array indices.
{
echo -n " " # Provides the tilt.
# Explain why.
if [[ "$1" -ge 0 && "$1" -lt "$Rows" && "$2" -ge 0 && "$2" -lt "$Columns" ]]
then
let "index = $1 * $Rows + $2"
# Now, print it rotated.
echo -n " ${alpha[index]}" # alpha[$row][$column]
echo -n " ${alpha[index]}"
# alpha[$row][$column]
fi
}
@ -76,13 +79,13 @@ fi
rotate () # Rotate the array 45 degrees
{ # ("balance" it on its lower lefthand corner).
rotate () # Rotate the array 45 degrees
{ #+ ("balance" it on its lower lefthand corner).
local row
local column
for (( row = Rows; row > -Rows; row-- )) # Step through the array backwards.
do
for (( row = Rows; row > -Rows; row-- ))
do # Step through the array backwards.
for (( column = 0; column < Columns; column++ ))
do
@ -103,14 +106,14 @@ do
done
# Array rotation inspired by examples (pp. 143-146) in
# "Advanced C Programming on the IBM PC", by Herbert Mayer
# (see bibliography).
# Array rotation inspired by examples (pp. 143-146) in
#+ "Advanced C Programming on the IBM PC", by Herbert Mayer
#+ (see bibliography).
}
#-----------------------------------------------------#
#--------------- Now, let the show begin. ------------#
load_alpha # Load the array.
print_alpha # Print it out.
rotate # Rotate it 45 degrees counterclockwise.

View File

@ -38,7 +38,7 @@ exit 0
# Additional notes (from the author of this script):
# -------------------------------------------------
# 1) Linux allows the users option in the /etc/fstab
# 1) Linux allows the "users" option in the /etc/fstab
# file so that any user can mount removable media.
# But, on a server, I like to allow only a few
# individuals access to removable media. I find
@ -53,4 +53,3 @@ exit 0
# control over which access can be mounted by using this
# same technique in separate mntfloppy, mntcdrom,
# and mntsamba scripts.

View File

@ -3,7 +3,7 @@
#
# This script filters the output of "strings" by checking it
#+ against a standard word list file.
# This effectively eliminates all the gibberish and noise,
# This effectively eliminates gibberish and noise,
#+ and outputs only recognized words.
# =================================================================
@ -30,7 +30,7 @@ MINSTRLEN=3 # Minimum string length.
WORDFILE=/usr/share/dict/linux.words # Dictionary file.
# May specify a different
#+ word list file
#+ of format 1 word per line.
#+ of one-word-per-line format.
wlist=`strings "$1" | tr A-Z a-z | tr '[:space:]' Z | \
@ -64,7 +64,9 @@ do
continue
fi
grep -Fw $word "$WORDFILE" # Match whole words only.
grep -Fw $word "$WORDFILE" # Match whole words only.
# ^^^ # "Fixed strings" and
#+ "whole words" options.
done