This commit is contained in:
gferg 2008-07-20 23:16:47 +00:00
parent 647f42a3c1
commit ee92aa5778
66 changed files with 2558 additions and 817 deletions

View File

@ -7,16 +7,150 @@
==================================================================
Current version = 5.3
http://personal.riverusers.com/~thegrendel/abs-guide-5.3.tar.bz2
Current version = 5.4
http://personal.riverusers.com/~thegrendel/abs-guide-5.4.tar.bz2
http://personal.riverusers.com/~thegrendel/abs-guide.pdf
--------------------------------------------------------------------
News: "Petals Around the Rose" (petals.sh) example script added.
"Crossword Puzzle Solver" (cw-solver.sh) example script added.
"Perquackey" type game (qky.sh) example script added.
News: "music.sh" example script added.
"nim.sh" example script added.
"UseGetOpt.sh" script added.
====================================================================
Version 5.4, Angleberry release
05/21/08
1) In "Tests" chapter:
In "Test Constructs" section:
Rewrote "arithmetic expansion" discussion and in-line example.
Removed "if-echo" construct example (too confusing).
In "File test Operators" section:
At "-b" entry, added short usage example.
Added a few lines to "arith-tests.sh" example.
In "Test Comparison Operators" section:
At "-z" entry, added short in-line example.
2) In "Introduction to Variables and Parameters" chapter:
In "Variable Substitution" section,
Added in-line example to "warning" about unassigned variables.
Minor cleanups to introductory text.
In "Special Variable Types" section,
at discussion of "du" overflow, noted that this has been
fixed as of kernel 2.6.23. (Thank you, Mauro Giachero,
for pointing this out.)
3) In "Loops and Branches" chapter:
Added in-line example of a function providing the [list]
for a "for" loop, using command substitution.
At "until" loops section, expanded "ex27.sh" example script.
4) In "Functions" chapter:
Added comment to the effect that a function call is equivalent to a
command.
5) In "Internal Commands and Builtins" chapter:
At footnote to "getopts" entry, fixed typo.
At "let" entry, added to "ex46.sh" example to include C-style
increment, decrement, and trinary operators.
6) In "External Commands" chapter:
In "Text Processing" section:
At "recode" entry, fixed typo (removed extraneous ">").
In "Math Commands" section:
At "factor" entry, added "primes2.sh" example script.
In "Time/Date Commands" section:
At "sleep" entry, fixed typo in usage example.
At "date" entry, fixup:
delete "generate six-digit random integers" &&
add explanation in <programlisting>
In "File and Archiving Commands" section:
At "more/less" entry, added paragraph (with link) explaining that
"less" displays man page source.
At "diff3" entry, added listing for "merge."
In "Miscellaneous Commands" section:
At "tee" entry, fixed typo (siponing -> siphoning).
At "m4" entry, clarified footnote definition of "macro."
At "getopt" entry, added Peggy Russell's note about the necessity
of "eval."
At "yes" entry,
Added a use (of sorts) for parsed-variable
echoing capability.
Cleared up ambiguity about "yes" parsing variables (it doesn't).
Added simple emulation of "yes" in a script function.
In "Communications Commands" section:
Added "mailstats" command.
In "Terminal Commands" section:
Added "resize" entry.
At "tput" entry, added listing of some interesting options.
7) In "Arrays" chapter:
Fixed error and typos in "array-strops.sh" example.
Added comment line to "ex67.sh" example about ${Array[$element]}.
(Thank you Juan Bellon, for the the heads-up on the above!)
Revisions and fixups to "empty-array.sh" example script
(Thank you, Nathan Coulter!)
8) In "Variables Revisited" chapter:
In "Manipulating Strings" section:
Minor rewrites to clarify meaning ("strip" --> "delete" ... etc.)
In "Indirect References" section:
Complete rewrite of introduction for additional clarity.
Added material to "ind-ref.sh" example.
In "Typing Variables" section:
Added short in-line example to footnote.
9) In the "Shell Wrappers" section of "Miscellany" chapter:
Fixed a typo in "ex3.sh" example ("This match lines ..." -->
"This matches lines ...").
Added mention of Martin Matusiak's "undvd" shell wrapper script.
Added mention of Itzchak Rehberg's "Ext3Undel" package.
10) In "Escaping" section of "Quoting" Chapter:
Minor fixups and clarifications.
11) In "/dev" section of "/dev and /proc" chapter:
Added "music.sh" example script (plays music!). Thanks, Antonio Macchi!)
Added links / short explanations to pseudo-device listing.
12) Slight stylistic revisions to "Credits" section "Endnotes" Chapter.
13) In "Debugging" chapter:
Added explanations and references to listing of internal variables
new to version 3 of Bash.
14) In "Restricted Shells" chapter:
Cleaned up markup tags (changed to <itemizedlist>).
15) In "Assorted Tips" section of "Miscellany" chapter:
Added "progress-bar.sh" example script. (Thanks, Dotan Barak!)
At "rcs" entry, correction: added space to "# $Id" in 2 places.
16) In "Special Characters" chapter:
At "whitespace" entry, added link to "[:space:]" POSIX character
class.
17) In "Contributed Scripts" appendix:
Added "maned.sh" -- man page editor example script.
Added "sd.sh" -- Standard Deviation example script.
Added "nim.sh" -- game of Nim example script.
Added Peggy Russell's "UseGetOpt.sh" example script (thanks!).
Slight fixup to "tohtml.sh" (more accurate conversion).
18) In "Writing Scripts" section of "Exercises" appendix:
Added "Craps" exercise.
Added "Tic-tac-toe" exercise.
Added "Banner" exercise.
Added "Table of Logarithms" exercise.
19) In "Bibliography" section:
Added entry+link to John Lion's _Commentary_
(still da bestest UNIX reference).
20) Cleanups/fixups to main text, appendices, and script examples where
appropriate . . . especially to older scripts.
Version 5.3, Goldenberry release
05/11/08

View File

@ -446,6 +446,14 @@
new notation</para>
</listitem>
<listitem>
<para><command>${!#}</command></para>
<para><link linkend="lastargref">Final <firstterm>positional
parameter</firstterm></link>.
(This is an <firstterm>indirect reference</firstterm> to
<link linkend="clacountref">$#</link>.)</para>
</listitem>
<listitem>
<para><command>${!varprefix*}</command></para>
<para><command>${!varprefix@}</command></para>
@ -688,6 +696,9 @@
<para><command>-a </command>
<link linkend="compoundand">Logical AND</link>
compound comparison test</para>
<para>Address database, <link linkend="ex30">script
example</link></para>
<para><firstterm>Advanced Bash Scripting Guide</firstterm>,
<link linkend="where_tarball">where to download</link></para>
@ -707,6 +718,9 @@
argument</link></para></listitem>
</itemizedlist></para>
<para><link linkend="logops1"><firstterm>And</firstterm> logical
operator</link> <command>&&</command></para>
<para><link linkend="anglebrac">Angle brackets</link>,
<firstterm>escaped</firstterm>,
<command>\&lt; . . . \&gt; </command>
@ -800,12 +814,13 @@
<listitem><para>As <link linkend="retarray">
<firstterm>return value</firstterm> from
a function</link></para></listitem>
<listitem><para><link
linkend="arrayspecialprops">Special properties</link>,
<firstterm>example script</firstterm></para></listitem>
<listitem><para><link
linkend="arraystringops">String operations</link>,
<firstterm>example script</firstterm></para></listitem>
<listitem><para>Special properties,
<link linkend="arrayspecialprops">example
script</link></para></listitem>
<listitem><para>String operations,
<link linkend="arraystringops">example
script</link></para></listitem>
<listitem><para><link
linkend="arrayunset"><firstterm>unset</firstterm> deletes array
elements</link></para></listitem>
@ -1032,6 +1047,8 @@
<para><link linkend="communications">Communications and
hosts</link></para>
<para><link linkend="ccomparison1">Compound comparison</link>
operators</para>
@ -1210,8 +1227,10 @@
external <firstterm>echo</firstterm> command</para></listitem>
</itemizedlist></para>
<para><link linkend="elifref1"><command>elif</command></link>, Contraction
of <firstterm>else</firstterm> and <firstterm>if</firstterm></para>
<para><link linkend="elifref1">elif</link>,
Contraction of <firstterm>else</firstterm>
and <link linkend="ifthen">if</link></para>
<para><link linkend="elseref">else</link></para>
<para><link linkend="caseesac1">esac</link>, keyword terminating
<firstterm>case</firstterm> construct</para>
<para><link linkend="envref"><firstterm>Environmental</firstterm>
@ -1235,6 +1254,8 @@
<listitem><para><link linkend="evalforced">Forces
<firstterm>reevaluation</firstterm></link> of
arguments</para></listitem>
<listitem><para>And <link linkend="evalindref">indirect
references</link></para></listitem>
<listitem><para><link linkend="evalrisk">Risk of
using</link></para></listitem>
</itemizedlist></para>
@ -1268,6 +1289,9 @@
<para><link
linkend="exitsuccess"><firstterm>Successful</firstterm></link>,
<command>0</command></para>
<para><link
linkend="sysexitsref"><filename>/usr/include/sysexits.h</filename></link>,
system file listing C/C++ standard exit codes</para>
</listitem>
</itemizedlist></para>
@ -1316,9 +1340,19 @@
<para>* * *</para>
<para><link linkend="factorref">factor</link>, decomposes an
integer into its prime factors
<itemizedlist>
<listitem><para>Application: <link linkend="primes2">Generating
prime numbers</link></para></listitem>
</itemizedlist></para>
<para><link linkend="falseref">false</link>,
returns <firstterm>unsuccessful</firstterm> (1) <link
linkend="exitstatusref">exit status</link></para>
<para><link linkend="filearchiv">Files / Archiving</link></para>
<para><link linkend="fdref">File descriptors</link></para>
<itemizedlist>
<listitem><para><link linkend="cfd">Closing</link></para>
@ -1402,11 +1436,11 @@
<listitem>
<para><link linkend="returnref">return</link></para>
<para>Multiple return values from a function,
<link linkend="stddev">example script</link></para>
<para><link linkend="retarray">
Returning an <firstterm>array</firstterm></link> from
a function</para>
<para><link linkend="rvt"><firstterm>return</firstterm>
range limits</link>, workarounds</para>
</listitem>
@ -1418,6 +1452,36 @@
<para>* * *</para>
<para>Games and amusements
<itemizedlist>
<listitem><para><link
linkend="agram">Anagrams</link></para></listitem>
<listitem><para><link
linkend="agram2">Anagrams</link>, again</para></listitem>
<listitem><para><link linkend="cwsolver">Crossword puzzle
solver</link></para></listitem>
<listitem><para><link
linkend="cryptoquote">Crypto-Quotes</link></para></listitem>
<listitem><para><link
linkend="horserace">Horse race</link></para></listitem>
<listitem><para><link linkend="lifeslow"><quote>Life</quote>
game</link></para></listitem>
<listitem><para><link linkend="musicscr">Music-playing
script</link></para></listitem>
<listitem><para><link linkend="nim">Nim</link></para></listitem>
<listitem><para><link
linkend="brownian">Pachinko</link></para></listitem>
<listitem><para><link
linkend="qky">Perquackey</link></para></listitem>
<listitem><para><link
linkend="petals">Petals Around the Rose</link></para></listitem>
<listitem><para><link
linkend="bashpodder">Podcasting</link></para></listitem>
<listitem><para><link linkend="poem">Poem</link></para></listitem>
<listitem><para><link
linkend="hanoi">Towers of Hanoi</link></para></listitem>
</itemizedlist></para>
<para><link linkend="getopty">getopt</link>,
<firstterm>external</firstterm> command for parsing script
<firstterm>command-line</firstterm> arguments
@ -1443,6 +1507,8 @@
<para><link linkend="gt0ref"> -gt </link>,
<firstterm>greater-than</firstterm> <link linkend="icomparison1">integer
comparison</link> test</para>
<para><link linkend="groffref"><firstterm>groff</firstterm></link>,
text markup and formatting language</para>
<para><link linkend="groupsref"><varname>$GROUPS</varname></link>,
<firstterm>Groups</firstterm> user belongs to</para>
<para><link linkend="gzipref">gzip</link>, compression utility</para>
@ -1538,6 +1604,10 @@
<para>* * *</para>
<!-- ********************** -->
<para><link linkend="rcsref"><varname>$Id</varname>
parameter</link>, in <firstterm>rcs</firstterm> (Revision Control
System)</para>
<para><link linkend="ifthen">if [ condition ]; then ...</link>
<firstterm>test</firstterm> construct
<itemizedlist>
@ -1577,9 +1647,8 @@
<para><link linkend="ivrref">Indirect referencing of variables</link>
<itemizedlist>
<listitem><para><link linkend="ivr2">New notation</link>, introduced
in version 2 of Bash</para></listitem>
<listitem><para><link linkend="varrefnew">
Example script</link></para></listitem>
in <link linkend="bash2ref">version 2</link> of Bash (<link
linkend="varrefnew"> example script</link>)</para></listitem>
</itemizedlist></para>
<!-- ********************** -->
@ -1620,8 +1689,15 @@
<para><link linkend="le0ref"> -le </link>,
<firstterm>less-than or equal</firstterm>
<link linkend="icomparison1">integer comparison</link> test</para>
<para><link linkend="letref">let</link>,
setting and carrying out arithmetic operations on variables</para>
setting and carrying out arithmetic operations on variables
<itemizedlist>
<listitem><para><firstterm>C-style</firstterm>
<link linkend="ex46">increment and decrement
operators</link></para></listitem>
</itemizedlist></para>
<para><link linkend="limitstringref">Limit string</link>,
in a <link linkend="heredocref">here document</link></para>
<para><link linkend="linenoref"><varname>$LINENO</varname></link>,
@ -1775,7 +1851,9 @@
<para><link linkend="makefileref"><filename>Makefile</filename></link>,
file containing the list of dependencies used by <link
linkend="makeref">make</link> command</para>
<para><link linkend="metameaningref">meta-meaning</link></para>
<para><link linkend="maned">Man page editor</link> (script)</para>
<para><link linkend="mathc">Math commands</link></para>
<para><link linkend="metameaningref">Meta-meaning</link></para>
<para><link linkend="moduloref">Modulo</link>, arithmetic
<firstterm>remainder</firstterm> operator
@ -1813,6 +1891,8 @@
<para><link linkend="noclobberref"><firstterm>Noclobber</firstterm></link>,
<option>-C</option> option to Bash to prevent overwriting
of files</para>
<para><link linkend="logops1"><firstterm>NOT</firstterm> logical
operator</link>, <command>!</command></para>
<para><link linkend="nullvar"><firstterm>null</firstterm> variable
assignment</link>, avoiding</para>
@ -1839,8 +1919,8 @@
linkend="setref">set</link> command</para>
<para><link linkend="orlistref"><firstterm>Or</firstterm>
list</link></para>
<para><link linkend="orref">Or logical operator</link>,
<command>||</command></para>
<para><link linkend="orref"><firstterm>Or</firstterm> logical
operator</link>, <command>||</command></para>
<para>* * *</para>
@ -2101,7 +2181,11 @@
<para>Prime numbers
<itemizedlist>
<listitem><para>Generating primes
<link linkend="primes1">without using arrays</link></para></listitem>
<link linkend="primes2">using the <firstterm>factor</firstterm>
command</link></para></listitem>
<listitem><para>Generating primes
<link linkend="primes1">using the <firstterm>modulo</firstterm>
operator</link></para></listitem>
<listitem><para><link linkend="primes0">Sieve of
Eratosthenes</link></para></listitem>
</itemizedlist></para>
@ -2553,8 +2637,9 @@
<para><link linkend="scharlist1">Special characters</link></para>
<para>Stack, emulating a push-down, <link
linkend="stackex0"><firstterm>Example
linkend="stackex0"><firstterm>example
script</firstterm></link></para>
<para>Standard Deviation, <link linkend="stddev">example script</link></para>
<para><link linkend="filesref1">Startup files</link>, Bash</para>
<para><link linkend="stdinoutdef"><filename>stdin</filename>
@ -2599,6 +2684,11 @@
linkend="strlen">equivalent of</link></para>
</listitem>
<listitem>
<para><link linkend="stringsref">strings</link> command,
find printable strings in a binary or data file</para>
</listitem>
<listitem>
<para>Substring extraction</para>
<para><link linkend="substrextr01">${string:position}</link></para>
@ -2689,6 +2779,8 @@
<para>* * *</para>
<para>Table lookup, <link linkend="resistor">script
example</link></para>
<para><link linkend="tailref">tail</link>, <firstterm>echo</firstterm>
to <filename>stdout</filename> lines at the (tail) end of a text
file</para>
@ -2697,13 +2789,14 @@
output of command(s) partway through a <link
linkend="piperef">pipe</link></para>
<para><link linkend="terminalsref">Terminals</link>
<para><link linkend="terminalssys1">Terminals</link>
<itemizedlist>
<listitem><para><link
linkend="setserialref">setserial</link></para></listitem>
<listitem><para><link
linkend="settermref">setterm</link></para></listitem>
<listitem><para><link linkend="sttyref">stty</link></para></listitem>
<listitem><para><link linkend="tputref">tput</link></para></listitem>
<listitem><para><link linkend="wallref">wall</link></para></listitem>
</itemizedlist></para>
@ -2813,6 +2906,12 @@
</listitem>
</itemizedlist></para>
<!-- *************************************************************** -->
<para><link linkend="textproc">Text and text file
processing</link></para>
<para><link linkend="timedate">Time / Date</link></para>
<!-- *************************************************************** -->
<para>Timed input
<itemizedlist>
@ -2879,14 +2978,16 @@
<listitem><para><link
linkend="prependref"><firstterm>Prepending</firstterm></link>
lines at head of a file</para></listitem>
<listitem><para><link linkend="progressbar">Progress
bar</link> template</para></listitem>
<listitem><para><link
linkend="pseudocoderef">Pseudo-code</link></para></listitem>
<listitem><para>Script<link linkend="scriptasemb"> as embedded
command</link></para></listitem>
<listitem><para><link linkend="rcsref">rcs</link></para></listitem>
<listitem><para><link linkend="runpartsref2">Running scripts in
sequence</link> without user intervention, using <link
linkend="runpartsref">run-parts</link></para></listitem>
<listitem><para>Script<link linkend="scriptasemb"> as embedded
command</link></para></listitem>
<listitem>
<para>Script <firstterm>portability</firstterm></para>
<para><link
@ -2916,7 +3017,9 @@
<para><link linkend="tmoutref"><varname>$TMOUT</varname></link>,
Timeout interval</para>
Timeout interval</para>
<para><link linkend="tputref">tput</link>, terminal-control
command</para>
<para><link linkend="trref">tr</link>, character translation filter
<itemizedlist>
@ -2934,8 +3037,18 @@
<para><link linkend="trapref1"><firstterm>Trap</firstterm></link>,
specifying an action upon receipt of a <link
linkend="signald">signal</link></para>
<para><link linkend="cstrinary">Trinary operator</link>,
<firstterm>C</firstterm>-style</para>
<para><firstterm>Trinary</firstterm> operator,
<firstterm>C</firstterm>-style,
<userinput>var>10?88:99</userinput>
<itemizedlist>
<listitem><para><link linkend="cstrinary">in
<firstterm>double-parentheses</firstterm>
construct</link></para></listitem>
<listitem><para><link linkend="ex46">in <firstterm>let</firstterm>
construct</link></para></listitem>
</itemizedlist></para>
<para><link linkend="trueref">true</link>,
returns <firstterm>successful</firstterm> (0) <link
linkend="exitstatusref">exit status</link></para>
@ -3077,6 +3190,15 @@
<para><link linkend="whileloopref">while</link> loop</para>
<para><firstterm>while [ condition ]; do</firstterm>
<itemizedlist>
<listitem><para><link linkend="whloopc">C-style syntax</link>
</para></listitem>
<listitem><para><link linkend="whilefunc">Calling a
<firstterm>function</firstterm> within
<firstterm>test</firstterm> brackets</link></para></listitem>
<listitem><para><link linkend="whmultcond">Multiple
conditions</link></para></listitem>
<listitem><para><link linkend="whilenobrackets">Omitting
<firstterm>test</firstterm> brackets</link></para></listitem>
<listitem><para><link linkend="whilereadref2">
<firstterm>while read</firstterm></link>
construct</para></listitem>
@ -3094,10 +3216,12 @@
document</firstterm>, error</para></listitem>
<listitem><para><link linkend="wsbcomm">Preceding script
comments</link></para></listitem>
<listitem><para><link
linkend="wsquo"><firstterm>Quoting</firstterm></link>,
to preserve <firstterm>whitespace</firstterm> within strings
or variables</para></listitem>
<listitem><para><link
linkend="wsquo"><firstterm>Quoting</firstterm></link>,
to preserve <firstterm>whitespace</firstterm> within strings
or variables</para></listitem>
<listitem><para><link linkend="wsposix">[:space:]</link>,
<firstterm>POSIX</firstterm> character class</para></listitem>
</itemizedlist></para>
<para><link linkend="whoref">who</link>, information about logged on users
@ -3129,7 +3253,11 @@
<para>* * *</para>
<para><link linkend="yesref">yes</link></para>
<para><link linkend="yesref">yes</link>
<itemizedlist>
<listitem><para><link
linkend="yesemu">Emulation</link></para></listitem>
</itemizedlist></para>
<para>* * *</para>

View File

@ -93,12 +93,24 @@ tree2.sh:
line 88
petals.sh
line 54
line 56
realname.sh
line 26
qky.sh
line 7
line 63
line 87
line 113
(The unaltered, executable script can be downloaded from
http://personal.riverusers.com/~thegrendel/qky.sh)
(The unaltered, executable script can be downloaded. See:
http://personal.riverusers.com/~thegrendel/qky.README.html)
maned.sh
line 6 (comment)
progress-bar.sh
line 26
line 30
nim.sh
line 27

View File

@ -0,0 +1,123 @@
#!/bin/bash
# UseGetOpt.sh
# Author: Peggy Russell &lt;prusselltechgroup@gmail.com&gt;
UseGetOpt () {
declare inputOptions
declare -r E_OPTERR=85
declare -r ScriptName=${0##*/}
declare -r ShortOpts="adf:hlt"
declare -r LongOpts="aoption,debug,file:,help,log,test"
DoSomething () {
echo "The function name is '${FUNCNAME}'"
# Recall that $FUNCNAME is an internal variable
#+ holding the name of the function it is in.
}
inputOptions=$(getopt -o "${ShortOpts}" --long \
"${LongOpts}" --name "${ScriptName}" -- "${@}")
if [[ ($? -ne 0) || ($# -eq 0) ]]; then
echo "Usage: ${ScriptName} [-dhlt] {OPTION...}"
exit $E_OPTERR
fi
eval set -- "${inputOptions}"
# Only for educational purposes. Can be removed.
#-----------------------------------------------
echo "++ Test: Number of arguments: [$#]"
echo '++ Test: Looping through "$@"'
for a in "$@"; do
echo " ++ [$a]"
done
#-----------------------------------------------
while true; do
case "${1}" in
--aoption | -a) # Argument found.
echo "Option [$1]"
;;
--debug | -d) # Enable informational messages.
echo "Option [$1] Debugging enabled"
;;
--file | -f) # Check for optional argument.
case "$2" in #+ Double colon is optional argument.
"") # Not there.
echo "Option [$1] Use default"
shift
;;
*) # Got it
echo "Option [$1] Using input [$2]"
shift
;;
esac
DoSomething
;;
--log | -l) # Enable Logging.
echo "Option [$1] Logging enabled"
;;
--test | -t) # Enable testing.
echo "Option [$1] Testing enabled"
;;
--help | -h)
echo "Option [$1] Display help"
break
;;
--) # Done! $# is argument number for "--", $@ is "--"
echo "Option [$1] Dash Dash"
break
;;
*)
echo "Major internal error!"
exit 8
;;
esac
echo "Number of arguments: [$#]"
shift
done
shift
# Only for educational purposes. Can be removed.
#----------------------------------------------------------------------
echo "++ Test: Number of arguments after \"--\" is [$#] They are: [$@]"
echo '++ Test: Looping through "$@"'
for a in "$@"; do
echo " ++ [$a]"
done
#----------------------------------------------------------------------
}
################################### M A I N ########################
# If you remove "function UseGetOpt () {" and corresponding "}",
#+ you can uncomment the "exit 0" line below, and invoke this script
#+ with the various options from the command line.
#-------------------------------------------------------------------
# exit 0
echo "Test 1"
UseGetOpt -f myfile one "two three" four
echo;echo "Test 2"
UseGetOpt -h
echo;echo "Test 3 - Short Options"
UseGetOpt -adltf myfile anotherfile
echo;echo "Test 4 - Long Options"
UseGetOpt --aoption --debug --log --test --file myfile anotherfile
exit

File diff suppressed because it is too large Load Diff

View File

@ -38,4 +38,4 @@ chmod 777 $MOUNTPOINT # Makes new drive accessible to all users.
# Add the following line to /etc/fstab.
# /dev/hdb1 /mnt/newdisk ext2 defaults 1 1
exit 0
exit

View File

@ -1,5 +1,5 @@
#!/bin/bash
# allprofs.sh: print all user profiles
# allprofs.sh: Print all user profiles.
# This script written by Heiner Steven, and modified by the document author.

View File

@ -34,4 +34,16 @@ echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1
# What would happen if it were removed?
# Try removing it, then rerunning the script.
# ======================================= #
# (( ... )) also useful in an if-then test.
var1=5
var2=4
if (( var1 > var2 ))
then #^ ^ Note: Not $var1, $var2. Why?
echo "$var1 is greater than $var2"
fi # 5 is greater than 4
exit 0

View File

@ -1,10 +1,12 @@
#!/bin/bash
# array-strops.sh: String operations on arrays.
# Script by Michael Zick.
# Used with permission.
# In general, any string operation in the ${name ... } notation
#+ can be applied to all string elements in an array
# Script by Michael Zick.
# Fixups: 05 May 08
# Used in ABS Guide with permission.
# In general, any string operation using the ${name ... } notation
#+ can be applied to all string elements in an array,
#+ with the ${name[@] ... } or ${name[*] ...} notation.
@ -14,19 +16,20 @@ echo
# Trailing Substring Extraction
echo ${arrayZ[@]:0} # one two three four five five
# All elements.
# ^ All elements.
echo ${arrayZ[@]:1} # two three four five five
# All elements following element[0].
# ^ All elements following element[0].
echo ${arrayZ[@]:1:2} # two three
# Only the two elements after element[0].
# ^ Only the two elements after element[0].
echo "-----------------------"
# Substring Removal
# Removes shortest match from front of string(s),
#+ where the substring is a regular expression.
# Substring Removal
# Removes shortest match from front of string(s).
echo ${arrayZ[@]#f*r} # one two three five five
# Applied to all elements of the array.
@ -51,54 +54,61 @@ echo "-----------------------"
# Substring Replacement
# Replace first occurance of substring with replacement
# Replace first occurrence of substring with replacement.
echo ${arrayZ[@]/fiv/XYZ} # one two three four XYZe XYZe
# Applied to all elements of the array.
# ^ ^^^ ^^^ Applied to all elements of the array.
# Replace all occurances of substring
# Replace all occurrences of substring.
echo ${arrayZ[@]//iv/YY} # one two three four fYYe fYYe
# Applied to all elements of the array.
# Delete all occurances of substring
# Not specifing a replacement means 'delete'
# Delete all occurrences of substring.
# Not specifing a replacement means 'delete.'
echo ${arrayZ[@]//fi/} # one two three four ve ve
# Applied to all elements of the array.
# ^^ Applied to all elements of the array.
# Replace front-end occurances of substring
# Replace front-end occurrences of substring.
echo ${arrayZ[@]/#fi/XY} # one two three four XYve XYve
# Applied to all elements of the array.
# ^ Applied to all elements of the array.
# Replace back-end occurances of substring
# Replace back-end occurrences of substring.
echo ${arrayZ[@]/%ve/ZZ} # one two three four fiZZ fiZZ
# Applied to all elements of the array.
# ^ Applied to all elements of the array.
echo ${arrayZ[@]/%o/XX} # one twXX three four five five
# Why?
# ^ Why?
echo "-----------------------"
# Before reaching for awk (or anything else) --
# Recall:
# $( ... ) is command substitution.
# Functions run as a sub-process.
# Functions write their output to stdout.
# Assignment reads the function's stdout.
# The name[@] notation specifies a "for-each" operation.
newstr() {
echo -n "!!!"
}
echo ${arrayZ[@]/%e/$(newstr)}
# ^ ^^^^^^^^^
# on!!! two thre!!! four fiv!!! fiv!!!
# Q.E.D: The replacement action is an 'assignment.'
# Q.E.D: The replacement action is, in effect, an 'assignment.'
echo "-----------------------"
# Accessing the "For-Each"
echo ${arrayZ[@]//*/$(newstr optional_arguments)}
# Now, if Bash would just pass the matched string as $0
# !!! !!! !!! !!! !!! !!!
# Now, if Bash would only pass the matched string
#+ to the function being called . . .
echo
exit 0
# Before reaching for a Big Hammer -- awk, Perl, or anything else --
# recall:
# $( ... ) is command substitution.
# A function runs as a sub-process.
# A function writes its output to stdout.
# Assignment, in conjunction with 'echo' and command substitution,
#+ can read a function's stdout.
# The name[@] notation specifies a "for-each" operation.
# Bash is more powerful than you think!

View File

@ -10,7 +10,8 @@ exit 0
# =======================================================
#!/usr/bin/perl
# This part of the script must be invoked with -x option.
# This part of the script must be invoked with
# perl -x bashandperl.sh
print "Greetings from the Perl part of the script.\n";
# More Perl commands may follow here.

View File

@ -1,7 +1,8 @@
#! /bin/sh
# Strips off the header from a mail/News message i.e. till the first
# empty line
# Mark Moraes, University of Toronto
# empty line.
# Author: Mark Moraes, University of Toronto
# See the included file "Moraes-COPYRIGHT" for copyright info.
# ==> These comments added by author of this document.

View File

@ -77,7 +77,7 @@ Move () { # Move one unit right / left, or stay put.
Play () { # Single pass (inner loop).
i=0
while [ "$i" -lt "$ROWS" ] # One event per row.
while [ "$i" -lt "$ROWS" ] # One event per row.
do
Move
((i++));

View File

@ -1,31 +1,32 @@
#!/bin/bash
# Manipulating a variable, C-style, using the ((...)) construct.
# c-vars.sh
# Manipulating a variable, C-style, using the (( ... )) construct.
echo
(( a = 23 )) # Setting a value, C-style,
#+ with spaces on both sides of the "=".
echo "a (initial value) = $a"
echo "a (initial value) = $a" # 23
(( a++ )) # Post-increment 'a', C-style.
echo "a (after a++) = $a"
echo "a (after a++) = $a" # 24
(( a-- )) # Post-decrement 'a', C-style.
echo "a (after a--) = $a"
echo "a (after a--) = $a" # 23
(( ++a )) # Pre-increment 'a', C-style.
echo "a (after ++a) = $a"
echo "a (after ++a) = $a" # 24
(( --a )) # Pre-decrement 'a', C-style.
echo "a (after --a) = $a"
echo "a (after --a) = $a" # 23
echo
########################################################
# Note that, as in C, pre- and post-decrement operators
#+ have slightly different side-effects.
#+ have different side-effects.
n=1; let --n && echo "True" || echo "False" # False
n=1; let n-- && echo "True" || echo "False" # True
@ -37,8 +38,8 @@ echo
(( t = a<45?7:11 )) # C-style trinary operator.
# ^ ^ ^
echo "If a < 45, then t = 7, else t = 11."
echo "t = $t " # Yes!
echo "If a < 45, then t = 7, else t = 11." # a = 23
echo "t = $t " # t = 7
echo
@ -48,12 +49,12 @@ echo
# -----------------
# Chet Ramey seems to have snuck a bunch of undocumented C-style
#+ constructs into Bash (actually adapted from ksh, pretty much).
# In the Bash docs, Ramey calls ((...)) shell arithmetic,
# In the Bash docs, Ramey calls (( ... )) shell arithmetic,
#+ but it goes far beyond that.
# Sorry, Chet, the secret is now out.
# Sorry, Chet, the secret is out.
# See also "for" and "while" loops using the ((...)) construct.
# See also "for" and "while" loops using the (( ... )) construct.
# These work only with Bash, version 2.04 or later.
# These work only with version 2.04 or later of Bash.
exit 0
exit

View File

@ -1,9 +1,11 @@
#!/bin/bash
# This is a slight modification of the example file in the "column" man page.
# colms.sh
# A minor modification of the example file in the "column" man page.
(printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n" \
; ls -l | sed 1d) | column -t
# ^^^^^^ ^^
# The "sed 1d" in the pipe deletes the first line of output,
#+ which would be "total N",

View File

@ -5,7 +5,9 @@ PROCFILENAME=status # Where to look.
NOTCONNECTED=65
INTERVAL=2 # Update every 2 seconds.
pidno=$( ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME | awk '{ print $1 }' )
pidno=$( ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME |
awk '{ print $1 }' )
# Finding the process number of 'pppd', the 'ppp daemon'.
# Have to filter out the process lines generated by the search itself.
#

View File

@ -1,5 +1,6 @@
#!/bin/bash
# cw-solver.sh
# This is actually a wrapper around a one-liner (line 46).
# Crossword puzzle and anagramming word game solver.
# You know *some* of the letters in the word you're looking for,
@ -34,7 +35,7 @@ then #+ as a command-line argument . . .
echo "The x's represent known letters,"
echo "and the periods are unknown letters (blanks)."
echo "Letters and periods can be in any position."
echo "For example, try: cw-solver.sh w...i....n"
echo "For example, try: sh cw-solver.sh w...i....n"
echo
exit $E_NOPATT
fi
@ -49,7 +50,7 @@ grep ^"$1"$ "$DICT" # Yes, only one line!
# From _Stupid Grep Tricks_, vol. 1,
#+ a book the ABS Guide author may yet get around
#+ to writing one of these days . . .
#+ to writing . . . one of these days . . .
# ===============================================
echo
@ -58,9 +59,8 @@ exit $? # Script terminates here.
# If there are too many words generated,
#+ redirect the output to a file.
cw-solver w...i....n
$ sh cw-solver.sh w...i....n
twichildren
wellington
workingman
workingmen

View File

@ -2,7 +2,8 @@
# empty-array.sh
# Thanks to Stephane Chazelas for the original example,
#+ and to Michael Zick and Omair Eshkenazi for extending it.
#+ and to Michael Zick, Omair Eshkenazi, for extending it.
# And to Nathan Coulter for clarifications and corrections.
# An empty array is not the same as an array with empty elements.
@ -12,6 +13,7 @@
array2=( ) # No elements . . . "array2" is empty.
array3=( ) # What about this array?
echo
ListArray()
{
@ -54,8 +56,8 @@ array3[${#array3[*]}]="new2"
ListArray
# When extended as above; arrays are 'stacks'
# The above is the 'push'
# When extended as above, arrays are 'stacks' ...
# Above is the 'push' ...
# The stack 'height' is:
height=${#array2[@]}
echo
@ -71,7 +73,7 @@ echo "New stack height for array2 = $height"
ListArray
# List only 2nd and 3rd elements of array0.
from=1 # Zero-based numbering.
from=1 # Zero-based numbering.
to=2
array3=( ${array0[@]:1:2} )
echo
@ -108,25 +110,47 @@ echo "Elements in array8: ${array8[@]}"
# The string operations are performed on
#+ each of the elements in var[@] in succession.
# Therefore : Bash supports string vector operations
#+ if the result is a zero length string,
# Therefore : Bash supports string vector operations.
# If the result is a zero length string,
#+ that element disappears in the resulting assignment.
# However, if the expansion is in quotes, the null elements remain.
# Michael Zick: Question, are those strings hard or soft quotes?
# Nathan Coulter: There is no such thing as "soft quotes."
# What's really happening is that
#+ the pattern matching happens after all the other expansions of [word]
#+ in cases like ${parameter#word}.
# Question, are those strings hard or soft quotes?
zap='new*'
array9=( ${array0[@]/$zap/} )
echo
echo "Number of elements in array9: ${#array9[@]}"
array9=( "${array0[@]/$zap/}" )
echo "Elements in array9: ${array9[@]}"
# This time the null elements remain.
echo "Number of elements in array9: ${#array9[@]}"
# Just when you thought you where still in Kansas . . .
array10=( ${array0[@]#$zap} )
# Just when you thought you were still in Kansas . . .
array10=( ${array0[@]#"$zap"} )
echo
echo "Elements in array10: ${array10[@]}"
# But, the asterisk in zap won't be interpreted if quoted.
array10=( ${array0[@]#"$zap"} )
echo
echo "Elements in array10: ${array10[@]}"
# Well, maybe we _are_ still in Kansas . . .
# (Revisions to above code block by Nathan Coulter.)
# Compare array7 with array10.
# Compare array8 with array9.
# Answer: must be soft quotes.
# Compare array7 with array10.
# Compare array8 with array9.
exit 0
# Reiterating: No such thing as soft quotes!
# Nathan Coulter's explains:
# Pattern matching of 'word' in ${parameter#word} is done after
#+ parameter expansion and *before* quote removal.
# In the normal case, pattern matching is done *after* quote removal.
exit

View File

@ -10,7 +10,7 @@ echo "Testing \"0\""
if [ 0 ] # zero
then
echo "0 is true."
else
else # Or else ...
echo "0 is false."
fi # 0 is true.

View File

@ -1,18 +1,18 @@
#!/bin/bash
# zmore
#View gzipped files with 'more'
# View gzipped files with 'more' filter.
NOARGS=65
NOTFOUND=66
NOTGZIP=67
E_NOARGS=65
E_NOTFOUND=66
E_NOTGZIP=67
if [ $# -eq 0 ] # same effect as: if [ -z "$1" ]
# $1 can exist, but be empty: zmore "" arg2 arg3
then
echo "Usage: `basename $0` filename" >&2
# Error message to stderr.
exit $NOARGS
exit $E_NOARGS
# Returns 65 as exit status of script (error code).
fi
@ -20,24 +20,22 @@ filename=$1
if [ ! -f "$filename" ] # Quoting $filename allows for possible spaces.
then
echo "File $filename not found!" >&2
# Error message to stderr.
exit $NOTFOUND
echo "File $filename not found!" >&2 # Error message to stderr.
exit $E_NOTFOUND
fi
if [ ${filename##*.} != "gz" ]
# Using bracket in variable substitution.
then
echo "File $1 is not a gzipped file!"
exit $NOTGZIP
exit $E_NOTGZIP
fi
zcat $1 | more
# Uses the filter 'more.'
# May substitute 'less', if desired.
# Uses the 'more' filter.
# May substitute 'less' if desired.
exit $? # Script returns exit status of pipe.
# Actually "exit $?" is unnecessary, as the script will, in any case,
# return the exit status of the last command executed.
# Actually "exit $?" is unnecessary, as the script will, in any case,
#+ return the exit status of the last command executed.

View File

@ -12,4 +12,19 @@ do
echo
done
# ------------------------------------------- #
# As with "for" and "while" loops,
#+ an "until" loop permits C-like test constructs.
LIMIT=10
var=0
until (( var > LIMIT ))
do # ^^ ^ ^ ^^ No brackets, no $ prefixing variables.
echo -n "$var "
(( var++ ))
done # 0 1 2 3 4 5 6 7 8 9 10
exit 0

View File

@ -1,11 +1,11 @@
#!/bin/bash
# This is a simple script that removes blank lines from a file.
# This simple script removes blank lines from a file.
# No argument checking.
#
# You might wish to add something like:
#
# E_NOARGS=65
# E_NOARGS=85
# if [ -z "$1" ]
# then
# echo "Usage: `basename $0` target-file"
@ -13,14 +13,15 @@
# fi
sed -e /^$/d "$1"
# Same as
# sed -e '/^$/d' filename
# invoked from the command line.
sed -e /^$/d "$1"
# The '-e' means an "editing" command follows (optional here).
# '^' is the beginning of line, '$' is the end.
# This match lines with nothing between the beginning and the end,
# '^' indicates the beginning of line, '$' the end.
# This matches lines with nothing between the beginning and the end --
#+ blank lines.
# The 'd' is the delete command.
@ -30,4 +31,4 @@ sed -e /^$/d "$1"
# Note that this script doesn't actually change the target file.
# If you need to do that, redirect its output.
exit 0
exit

View File

@ -1,11 +1,12 @@
#!/bin/bash
# "subst", a script that substitutes one pattern for
# subst.sh: a script that substitutes one pattern for
#+ another in a file,
#+ i.e., "subst Smith Jones letter.txt".
#+ i.e., "sh subst.sh Smith Jones letter.txt".
# Jones replaces Smith.
ARGS=3 # Script requires 3 arguments.
E_BADARGS=65 # Wrong number of arguments passed to script.
E_BADARGS=85 # Wrong number of arguments passed to script.
if [ $# -ne "$ARGS" ]
# Test number of arguments to script (always a good idea).
@ -26,16 +27,15 @@ else
fi
# Here is where the heavy work gets done.
# -----------------------------------------------
# Here is where the heavy work gets done.
sed -e "s/$old_pattern/$new_pattern/g" $file_name
# -----------------------------------------------
# 's' is, of course, the substitute command in sed,
#+ and /pattern/ invokes address matching.
# The "g", or global flag causes substitution for *every*
# The 'g,' or global flag causes substitution for EVERY
#+ occurence of $old_pattern on each line, not just the first.
# Read the literature on 'sed' for an in-depth explanation.
# Read the 'sed' docs for an in-depth explanation.
exit 0 # Successful invocation of the script returns 0.
exit $?

View File

@ -24,6 +24,26 @@ let "a %= 8" # Equivalent to let "a = a % 8"
echo "270 modulo 8 = $a (270 / 8 = 33, remainder $a)"
# 6
# Does "let" permit C-style operators?
# Yes, just as the (( ... )) double-parentheses construct does.
let a++ # C-style (post) increment.
echo "6++ = $a" # 6++ = 7
let a-- # C-style decrement.
echo "7-- = $a" # 7-- = 6
# Of course, ++a, etc., also allowed . . .
echo
exit 0
# Trinary operator.
# Note that $a is 6, see above.
let "t = a<7?7:11" # True
echo $t # 7
let a++
let "t = a<7?7:11" # False
echo $t # 11
exit

View File

@ -39,10 +39,12 @@ do
done
return $number
# Exercise:
# --------
# Explain how this function works.
# Hint: division by successive subtraction.
# Exercises:
# ---------
# 1) Explain how this function works.
# Hint: division by successive subtraction.
# 2) Extend to range of the function.
# Hint: use "echo" and command-substitution capture.
}
@ -63,7 +65,9 @@ num=$?
to_roman $num 4 IV
num=$?
to_roman $num 1 I
# Successive calls to conversion function!
# Is this really necessary??? Can it be simplified?
echo
exit 0
exit

View File

@ -1,5 +1,5 @@
#!/bin/bash
# "and list"
# and list
if [ ! -z "$1" ] && echo "Argument #1 = $1" && [ ! -z "$2" ] \
&& echo "Argument #2 = $2"

View File

@ -1,9 +1,9 @@
#!/bin/bash
# delete.sh, not-so-cunning file deletion utility.
# delete.sh, a not-so-cunning file deletion utility.
# Usage: delete filename
E_BADARGS=65
E_BADARGS=85
if [ -z "$1" ]
then
@ -25,4 +25,4 @@ Cowardly refusing to delete a nonexistent file."
# Note logic inversion above.
# AND LIST executes on true, OR LIST on false.
exit 0
exit $?

View File

@ -27,6 +27,7 @@ index=0
while [ "$index" -lt "$element_count" ]
do # List all the elements in the array.
echo ${colors[$index]}
# ${colors[index]} also works because it's within ${ ... } brackets.
let "index = $index + 1"
# Or:
# index+=1

View File

@ -21,7 +21,7 @@ Primes[i=1]='' # 1 is not a prime.
until (( ( i += 1 ) > (${UPPER_LIMIT}/i) )) # Need check only ith-way.
do # Why?
if ((${Primes[t=i*(i-1), i]}))
# Obscure, but instructive, use of numeric eval in subscript.
# Obscure, but instructive, use of arithmetic expansion in subscript.
then
until (( ( t += i ) > ${UPPER_LIMIT} ))
do Primes[t]=; done

View File

@ -45,6 +45,7 @@ echo "Creating swap file of size $blocks blocks (KB)."
dd if=/dev/zero of=$FILE bs=$BLOCKSIZE count=$blocks # Zero out file.
mkswap $FILE $blocks # Designate it a swap file.
swapon $FILE # Activate swap file.
retcode=$? # Everything worked?
# Note that if one or more of these commands fails,
#+ then it could cause nasty problems.
######################################################################
@ -59,4 +60,4 @@ swapon $FILE # Activate swap file.
echo "Swap file created and activated."
exit $SUCCESS
exit $retcode

View File

@ -8,9 +8,11 @@
echo $'Ringing bell 3 times \a \a \a'
# May only ring once with certain terminals.
# Or ...
# May not ring at all, depending on terminal settings.
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.
# Octal equivalent of characters.
exit 0
exit

View File

@ -26,3 +26,5 @@ echo "Value of t changed to ${!t}" # 387
#+ would have been nice. Sigh.
exit 0
# See also, ind-ref.sh example.

View File

@ -11,7 +11,7 @@
# make sure /pipe really is a pipe and not a plain file
rm -rf /pipe
mkfifo /pipe # ==> Create a "named pipe", named "/pipe".
mkfifo /pipe # ==> Create a "named pipe", named "/pipe" ...
# ==> 'su xyz' runs commands as user "xyz".
# ==> 'ssh' invokes secure shell (remote login client).

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Two ways to count up to 10.
# Multiple ways to count up to 10.
echo
@ -13,6 +13,27 @@ echo; echo
# +==========================================+
# Using "seq" ...
for a in `seq 10`
do
echo -n "$a "
done
echo; echo
# +==========================================+
# Using brace expansion ...
# Bash, version 3+.
for a in {1..10}
do
echo -n "$a "
done
echo; echo
# +==========================================+
# Now, let's do the same, using C-like syntax.
LIMIT=10
@ -28,8 +49,8 @@ echo; echo
# Let's use the C "comma operator" to increment two variables simultaneously.
for ((a=1, b=1; a <= LIMIT ; a++, b++)) # The comma chains together operations.
do
for ((a=1, b=1; a <= LIMIT ; a++, b++))
do # The comma chains together operations.
echo -n "$a-$b "
done

View File

@ -106,3 +106,6 @@ rm -f ${TMPFILE}
# ==> ---------
# ==> 1) Add error checking.
# ==> 2) Add bells & whistles.
# See the included file "Moraes-COPYRIGHT" for copyright info.
#+ on this script.

View File

@ -29,7 +29,7 @@ getopt_simple $*
echo "test is '$test'"
echo "test2 is '$test2'"
exit 0
exit 0 # See also, UseGetOpt.sh, a modified versio of this script.
---
@ -42,3 +42,4 @@ Processing parameter of: '/test2=value2'
Parameter: 'test2', value: 'value2'
test is 'value1'
test2 is 'value2'

View File

@ -1,7 +1,7 @@
#!/bin/bash
# grp.sh: Very crude reimplementation of 'grep'.
# grp.sh: Rudimentary reimplementation of grep.
E_BADARGS=65
E_BADARGS=85
if [ -z "$1" ] # Check for argument to script.
then
@ -18,7 +18,7 @@ do
if [ ! -z "$output" ] # What happens if "$output" is not quoted?
then
echo -n "$file: "
echo $output
echo "$output"
fi # sed -ne "/$1/s|^|${file}: |p" is equivalent to above.
echo

View File

@ -1,16 +1,14 @@
#!/bin/bash
# hexconvert.sh: Convert a decimal number to hexadecimal.
E_NOARGS=65 # Command-line arg missing.
E_NOARGS=85 # Command-line arg missing.
BASE=16 # Hexadecimal.
if [ -z "$1" ]
then
then # Need a command line argument.
echo "Usage: $0 number"
exit $E_NOARGS
# Need a command line argument.
fi
# Exercise: add argument validity checking.
fi # Exercise: add argument validity checking.
hexcvt ()
@ -22,12 +20,12 @@ then
fi
echo ""$1" "$BASE" o p" | dc
# "o" sets radix (numerical base) of output.
# "p" prints the top of stack.
# See 'man dc' for other options.
# o sets radix (numerical base) of output.
# p prints the top of stack.
# For other options: 'man dc' ...
return
}
hexcvt "$1"
exit 0
exit

View File

@ -6,7 +6,7 @@
# License: Public Domain
# This script may be turned in to your instructor
#+ in fulfillment of ALL Bash scripting homework assignments.
#+ in fulfillment of ALL shell scripting homework assignments.
# It's sparsely commented, but you, the student, can easily remedy that.
# The script author repudiates all responsibility!
@ -73,14 +73,14 @@ b_r
for i in $(seq 0 $MAXL)
do
p_l "${L[i]}"
if [[ "$i" -eq "$P1" || "$i" -eq "$P2" || "$i" -eq "$P3" ]]
then
cr
elif [[ "$i" -eq "$PP1" || "$i" -eq "$PP2" ]]
then
cr; cr
fi
p_l "${L[i]}"
if [[ "$i" -eq "$P1" || "$i" -eq "$P2" || "$i" -eq "$P3" ]]
then
cr
elif [[ "$i" -eq "$PP1" || "$i" -eq "$PP2" ]]
then
cr; cr
fi
done
restore
@ -90,6 +90,7 @@ echo
exit $E_LZY
# An example of an obfuscated script that is difficult to understand,
#+ and frustrating to maintain.
# In your career as a sysadmin, you'll run into these all too often.
# A typical example of an obfuscated script that is difficult
#+ to understand, and frustrating to maintain.
# In your career as a sysadmin, you'll run into these critters
#+ all too often.

View File

@ -1,4 +1,6 @@
#!/bin/bash
# ifs.sh
# $IFS treats whitespace differently than other characters.
output_args_one_per_line()

View File

@ -2,6 +2,27 @@
# ind-ref.sh: Indirect variable referencing.
# Accessing the contents of the contents of a variable.
# First, let's fool around a little.
var=23
echo "\$var = $var" # $var = 23
# So far, everything as expected. But ...
echo "\$\$var = $$var" # $$var = 4570var
# Not meaningful. The contents of a memory location pointed to?
# Not useful at this point.
echo "\\\$\$var = \$$var" # \$$var = $23
# As expected. The first $ is escaped and pasted on to
#+ the value of var ($var = 23 ).
# Meaningful, but still not useful.
# Now, let's start over and do it the right way.
# ============================================== #
a=letter_of_alphabet # Variable "a" holds the name of another variable.
letter_of_alphabet=z
@ -11,8 +32,14 @@ echo
echo "a = $a" # a = letter_of_alphabet
# Indirect reference.
eval a=\$$a
echo "Now a = $a" # Now a = z
eval a=\$$a
# ^^^ Forcing an eval(uation), and ...
# ^ Escaping the first $ ...
# ------------------------------------------------------------------------
# The 'eval' forces an update of $a, sets it to the updated value of \$$a.
# So, we see why 'eval' so often shows up in indirect reference notation.
# ------------------------------------------------------------------------
echo "Now a = $a" # Now a = z
echo
@ -36,6 +63,7 @@ echo "\"table_cell_3\" now $table_cell_3"
echo -n "dereferenced \"t\" now "; eval echo \$$t
# "eval" takes the two arguments "echo" and "\$$t" (set equal to $table_cell_3)
echo
# (Thanks, Stephane Chazelas, for clearing up the above behavior.)

View File

@ -1,5 +1,5 @@
#!/bin/bash
# int-or-string.sh: Integer or string?
# int-or-string.sh
a=2334 # Integer.
let "a += 1"

View File

@ -1,27 +1,27 @@
#!/bin/bash
# life.sh: "Life in the Slow Lane"
# Version 2: Patched by Daniel Albers
#+ to allow non-square grids as input.
# Version 0.2: Patched by Daniel Albers
#+ to allow non-square grids as input.
# ##################################################################### #
# This is the Bash script version of John Conway's "Game of Life". #
# "Life" is a simple implementation of cellular automata. #
# --------------------------------------------------------------------- #
# On a rectangular grid, let each "cell" be either "living" or "dead". #
# On a rectangular grid, let each "cell" be either "living" or "dead." #
# Designate a living cell with a dot, and a dead one with a blank space.#
# Begin with an arbitrarily drawn dot-and-blank grid, #
#+ and let this be the starting generation, "generation 0." #
# Determine each successive generation by the following rules: #
# 1) Each cell has 8 neighbors, the adjoining cells #
#+ left, right, top, bottom, and the 4 diagonals. #
# 1) Each cell has 8 neighbors, the adjoining cells #
#+ left, right, top, bottom, and the 4 diagonals. #
# #
# 123 #
# 4*5 The * is the cell in question. #
# 4*5 The * is the cell under consideration. #
# 678 #
# #
# 2) A living cell with either 2 or 3 living neighbors remains alive. #
SURVIVE=2 #
# 3) A dead cell with 3 living neighbors becomes alive (a "birth"). #
# 3) A dead cell with 3 living neighbors comes alive (a "birth"). #
BIRTH=3 #
# 4) All other cases result in a dead cell for the next generation. #
# ##################################################################### #
@ -38,7 +38,7 @@ fi
############################################
# Abort script if "startfile" not specified
#+ and
#+ "gen0" not present.
#+ default file "gen0" not present.
E_NOSTARTFILE=68
@ -52,11 +52,11 @@ fi
ALIVE1=.
DEAD1=_
# Represent living and "dead" cells in the start-up file.
# Represent living and dead cells in the start-up file.
# ---------------------------------------------------------- #
# This script uses a 10 x 10 grid (may be increased,
#+ but a large grid will will cause very slow execution).
#+ but a large grid will slow execution).
ROWS=10
COLS=10
# Change above two variables to match grid size, as desired.
@ -66,7 +66,7 @@ GENERATIONS=10 # How many generations to cycle through.
# Adjust this upwards,
#+ if you have time on your hands.
NONE_ALIVE=80 # Exit status on premature bailout,
NONE_ALIVE=85 # Exit status on premature bailout,
#+ if no cells left alive.
TRUE=0
FALSE=1
@ -78,17 +78,16 @@ generation=0 # Initialize generation count.
# =================================================================
let "cells = $ROWS * $COLS" # How many cells.
let "cells = $ROWS * $COLS"
# How many cells.
declare -a initial # Arrays containing "cells."
# Arrays containing "cells."
declare -a initial
declare -a current
display ()
{
alive=0 # How many cells "alive" at any given time.
alive=0 # How many cells alive at any given time.
# Initially zero.
declare -a arr
@ -161,13 +160,12 @@ return $TRUE # Valid coordinate.
}
IsAlive () # Test whether cell is alive.
# Takes array, cell number, state of cell as arguments.
{
GetCount "$1" $2 # Get alive cell count in neighborhood.
IsAlive () # Test whether cell is alive.
# Takes array, cell number,
{ #+ state of cell as arguments.
GetCount "$1" $2 # Get alive cell count in neighborhood.
local nhbd=$?
if [ "$nhbd" -eq "$BIRTH" ] # Alive in any case.
then
return $ALIVE
@ -178,7 +176,7 @@ IsAlive () # Test whether cell is alive.
return $ALIVE
fi
return $DEAD # Default.
return $DEAD # Dead by default.
}
@ -216,7 +214,7 @@ GetCount () # Count live cells in passed cell's neighborhood.
let "t_bot = $bottom + $i"
let "row = $r" # Count center row of neighborhood.
let "row = $r" # Count center row.
IsValid $t_cen $row # Valid cell position?
if [ $? -eq "$TRUE" ]
then
@ -280,7 +278,7 @@ do
done
# let "generation += 1" # Increment generation count.
# let "generation += 1" # Increment generation count.
# Why was the above line commented out?
@ -293,7 +291,7 @@ echo "Generation $generation - $alive alive"
if [ "$alive" -eq 0 ]
then
echo
echo "Premature exit: no more cells alive!"
echo "Unexpected exit: no more cells alive!"
exit $NONE_ALIVE # No point in continuing
fi #+ if no live cells.
@ -328,7 +326,7 @@ echo "Generation $generation - $alive alive"
# -------------------------------------------
let "generation += 1" # Increment generation count.
let "generation += 1" # Bump generation count.
echo
# ------- Display second generation. -------
@ -349,7 +347,7 @@ done
echo
exit 0 # END
exit 0 # CEOF:EOF
@ -371,5 +369,4 @@ exit 0 # END
#+ in the script for an altered grid size.
#
# Exercise: Optimize this script.
# It has some repetitive and redundant code,
#+ for example, lines 335-336.
# It has some redundant code.

View File

@ -47,4 +47,4 @@ sed "$sedscript" $1 | fold -s --width=$MAXWIDTH
# An nice set of text processing utilities and an efficient
#+ scripting language provide an alternative to bloated executables.
exit 0
exit

View File

@ -0,0 +1,143 @@
#!/bin/bash
# maned.sh
# A rudimentary man page editor
# Version: 0.1 (Alpha, probably buggy)
# Author: Mendel Cooper &lt;thegrendel@theriver.com&gt;
# Reldate: 16 June 2008
# License: GPL3
savefile= # Global, used in multiple functions.
E_NOINPUT=90 # User input missing (error). May or may not be critical.
# =========== Markup Tags ============ #
TopHeader=".TH"
NameHeader=".SH NAME"
SyntaxHeader=".SH SYNTAX"
SynopsisHeader=".SH SYNOPSIS"
InstallationHeader=".SH INSTALLATION"
DescHeader=".SH DESCRIPTION"
OptHeader=".SH OPTIONS"
FilesHeader=".SH FILES"
EnvHeader=".SH ENVIRONMENT"
AuthHeader=".SH AUTHOR"
BugsHeader=".SH BUGS"
SeeAlsoHeader=".SH SEE ALSO"
BOLD=".B"
# Add more tags, as needed.
# See groff docs for markup meanings.
# ==================================== #
start ()
{
clear # Clear screen.
echo "ManEd"
echo "-----"
echo
echo "Simple man page creator"
echo "Author: Mendel Cooper"
echo; echo; echo
}
progname ()
{
echo -n "Program name? "
read name
echo -n "Manpage section? [Hit RETURN for default (\"1\") ] "
read section
if [ -z "$section" ]
then
section=1 # Most man pages are in section 1.
fi
if [ -n "$name" ]
then
savefile=""$name"."$section"" # Filename suffix = section.
echo -n "$1 " >>$savefile
name1=$(echo "$name" | tr a-z A-Z) # Change to uppercase,
#+ per man page convention.
echo -n "$name1" >>$savefile
else
echo "Error! No input." # Mandatory input.
exit $E_NOINPUT # Critical!
fi
echo -n " \"$section\"">>$savefile # Append, always append.
echo -n "Version? "
read ver
echo -n " \"Version $ver \"">>$savefile
echo >>$savefile
echo -n "Short description [0 - 5 words]? "
read sdesc
echo "$NameHeader">>$savefile
echo ""$BOLD" "$name"">>$savefile
echo "\- "$sdesc"">>$savefile
}
fill_in ()
{ # This function more or less copied from "pad.sh" script.
echo -n "$2? " # Get user input.
read var # May paste (a single line only!) to fill in field.
if [ -n "$var" ]
then
echo "$1 " >>$savefile
echo -n "$var" >>$savefile
else # Don't append empty field to file.
return $E_NOINPUT # Not critical here.
fi
echo >>$savefile
}
end ()
{
clear
echo -n "Would you like to view the saved man page (y/n)? "
read ans
if [ "$ans" = "n" -o "$ans" = "N" ]; then exit; fi
exec less "$savefile" # Exit script and hand off control to "less" ...
#+ ... which formats for viewing man page source.
}
# ---------------------------------------- #
start
progname "$TopHeader"
fill_in "$SynopsisHeader" "Synopsis"
fill_in "$DescHeader" "Long description"
# May paste in *single line* of text.
fill_in "$OptHeader" "Options"
fill_in "$FilesHeader" "Files"
fill_in "$AuthHeader" "Author"
fill_in "$BugsHeader" "Bugs"
fill_in "$SeeAlsoHeader" "See also"
# fill_in "$OtherHeader" ... as necessary.
end # ... exit not needed.
# ---------------------------------------- #
# Note that the generated man page will usually
#+ require manual fine-tuning with a text editor.
# However, it's a distinct improvement upon
#+ writing man source from scratch
#+ or even editing a blank man page template.
# The main deficiency of the script is that it permits
#+ pasting only a single text line into the input fields.
# This may be a long, cobbled-together line, which groff
# will automatically wrap and hyphenate.
# However, if you want multiple (newline-separated) paragraphs,
#+ these must be inserted by manual text editing on the
#+ script-generated man page.
# Exercise (difficult): Fix this!
# This script is not nearly as elaborate as the
#+ full-featured "manedit" package (http://wolfpack.twu.net),
#+ but it's much easier to use.

View File

@ -5,7 +5,7 @@
# It lets you look at the intermediate results on the fly
#+ while working on it.
E_WRONGARGS=65
E_WRONGARGS=85
if [ -z "$1" ]
then

View File

@ -1,18 +1,18 @@
#!/bin/bash
# match-string.sh: simple string matching
# match-string.sh: Simple string matching.
match_string ()
{
{ # Exact string match.
MATCH=0
NOMATCH=90
E_NOMATCH=90
PARAMS=2 # Function requires 2 arguments.
BAD_PARAMS=91
E_BAD_PARAMS=91
[ $# -eq $PARAMS ] || return $BAD_PARAMS
[ $# -eq $PARAMS ] || return $E_BAD_PARAMS
case "$1" in
"$2") return $MATCH;;
* ) return $NOMATCH;;
* ) return $E_NOMATCH;;
esac
}

View File

@ -0,0 +1,42 @@
#!/bin/bash
# music.sh
# MUSIC WITHOUT EXTERNAL FILES
# Author: Antonio Macchi
# Used in ABS Guide with permission
# /dev/dsp default = 8000 frames per second, 8 bits per frame (1 byte),
#+ 1 channel (mono)
duration=2000 # If 8000 bytes = 1 second, then 2000 = 1/4 second.
volume=$'\xc0' # Max volume = \xff (or \x00).
mute=$'\x80' # No volume = \x80 (the middle).
function mknote () # $1=Note Hz in bytes (e.g. A = 440Hz ::
#+ 8000 fps / 440 = 16 :: A = 16 bytes per second)
{
for t in `seq 0 $duration`
do
test $(( $t % $1 )) = 0 && echo -n $volume || echo -n $mute
done
}
e=`mknote 49`
g=`mknote 41`
a=`mknote 36`
b=`mknote 32`
c=`mknote 30`
cis=`mknote 29`
d=`mknote 27`
e2=`mknote 24`
n=`mknote 32767`
# European notation.
echo -n "$g$e2$d$c$d$c$a$g$n$g$e$n$g$e2$d$c$c$b$c$cis$n$cis$d \
$n$g$e2$d$c$d$c$a$g$n$g$e$n$g$a$d$c$b$a$b$c" > /dev/dsp
# dsp = Digital Signal Processor
exit $? # A "bonny" example of a shell script!

View File

@ -13,7 +13,7 @@ Semmelweiss
Smith
Turing
Venn
Wilson
Wilkinson
Znosko-Borowski
# This is a data file for

View File

@ -0,0 +1,275 @@
#!/bin/bash
# nim.sh: Game of Nim
# Author: Mendel Cooper
# Reldate: 15 July 2008
# License: GPL3
ROWS=5 # Five rows of pegs.
WON=91 # Exit codes to keep track of wins/losses.
LOST=92 # Possibly useful if running in batch mode.
QUIT=99
peg_msg= # Peg/Pegs?
Rows=( 0 5 4 3 2 1 ) # Array holding play info.
# ${Rows[0]} holds total number of pegs, updated after each turn.
# Other array elements hold number of pegs in corresponding row.
instructions ()
{
clear
tput bold
echo "Welcome to the game of Nim."; echo
echo -n "Do you need instructions? (y/n) "; read ans
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
clear
echo -e '\E[33;41m' # Yellow fg., over red bg.; bold.
cat &lt;&lt;INSTRUCTIONS
Nim is a game with roots in the distant past.
This particular variant starts with five rows of pegs.
1: | | | | |
2: | | | |
3: | | |
4: | |
5: |
The number at the left identifies the row.
The human player moves first, and alternates turns with the bot.
A turn consists of removing at least one peg from a single row.
It is permissable to remove ALL the pegs from a row.
For example, in row 2, above, the player can remove 1, 2, 3, or 4 pegs.
The player who removes the last peg loses.
The strategy consists of trying to be the one who removes
the next-to-last peg(s), leaving the loser with the final peg.
To exit the game early, hit ENTER during your turn.
INSTRUCTIONS
echo; echo -n "Hit ENTER to begin game. "; read azx
echo -e "\033[0m" # Restore display.
else tput sgr0; clear
fi
clear
}
tally_up ()
{
let "Rows[0] = ${Rows[1]} + ${Rows[2]} + ${Rows[3]} + ${Rows[4]} + \
${Rows[5]}" # Add up how many pegs remaining.
}
display ()
{
index=1 # Start with top row.
echo
while [ "$index" -le "$ROWS" ]
do
p=${Rows[index]}
echo -n "$index: " # Show row number.
# ------------------------------------------------
# Two concurrent inner loops.
indent=$index
while [ "$indent" -gt 0 ]
do
echo -n " " # Staggered rows.
((indent--)) # Spacing between pegs.
done
while [ "$p" -gt 0 ]
do
echo -n "| "
((p--))
done
# -----------------------------------------------
echo
((index++))
done
tally_up
rp=${Rows[0]}
if [ "$rp" -eq 1 ]
then
peg_msg=peg
final_msg="Game over."
else # Game not yet over . . .
peg_msg=pegs
final_msg="" # . . . So "final message" is blank.
fi
echo " $rp $peg_msg remaining."
echo " "$final_msg""
echo
}
player_move ()
{
echo "Your move:"
echo -n "Which row? "
while read idx
do # Validity check, etc.
if [ -z "$idx" ] # Hitting return quits.
then
echo "Premature exit."; echo
tput sgr0 # Restore display.
exit $QUIT
fi
if [ "$idx" -gt "$ROWS" -o "$idx" -lt 1 ] # Bounds check.
then
echo "Invalid row number!"
echo -n "Which row? "
else
break
fi
# TODO:
# Add check for non-numeric input.
# Also, script crashes on input outside of range of long double.
# Fix this.
done
echo -n "Remove how many? "
while read num
do # Validity check.
if [ -z "$num" ]
then
echo "Premature exit."; echo
tput sgr0 # Restore display.
exit $QUIT
fi
if [ "$num" -gt ${Rows[idx]} -o "$num" -lt 1 ]
then
echo "Cannot remove $num!"
echo -n "Remove how many? "
else
break
fi
done
# TODO:
# Add check for non-numeric input.
# Also, script crashes on input outside of range of long double.
# Fix this.
let "Rows[idx] -= $num"
display
tally_up
if [ ${Rows[0]} -eq 1 ]
then
echo " Human wins!"
echo " Congratulations!"
tput sgr0 # Restore display.
echo
exit $WON
fi
if [ ${Rows[0]} -eq 0 ]
then # Snatching defeat from the jaws of victory . . .
echo " Fool!"
echo " You just removed the last peg!"
echo " Bot wins!"
tput sgr0 # Restore display.
echo
exit $LOST
fi
}
bot_move ()
{
row_b=0
while [[ $row_b -eq 0 || ${Rows[row_b]} -eq 0 ]]
do
row_b=$RANDOM # Choose random row.
let "row_b %= $ROWS"
done
num_b=0
r0=${Rows[row_b]}
if [ "$r0" -eq 1 ]
then
num_b=1
else
let "num_b = $r0 - 1"
# Leave only a single peg in the row.
fi # Not a very strong strategy,
#+ but probably a bit better than totally random.
let "Rows[row_b] -= $num_b"
echo -n "Bot: "
echo "Removing from row $row_b ... "
if [ "$num_b" -eq 1 ]
then
peg_msg=peg
else
peg_msg=pegs
fi
echo " $num_b $peg_msg."
display
tally_up
if [ ${Rows[0]} -eq 1 ]
then
echo " Bot wins!"
tput sgr0 # Restore display.
exit $WON
fi
}
# ================================================== #
instructions # If human player needs them . . .
tput bold # Bold characters for easier viewing.
display # Show game board.
while [ true ] # Main loop.
do # Alternate human and bot turns.
player_move
bot_move
done
# ================================================== #
# Exercise:
# --------
# Improve the bot's strategy.
# There is, in fact, a Nim strategy that can force a win.
# See the Wikipedia article on Nim: http://en.wikipedia.org/wiki/Nim
# Recode the bot to use this strategy (rather difficult).
# Curiosities:
# -----------
# Nim played a prominent role in Alain Resnais' 1961 New Wave film,
#+ Last Year at Marienbad.
#
# In 1978, Leo Christopherson wrote an animated version of Nim,
#+ Android Nim, for the TRS-80 Model I.

View File

@ -57,4 +57,8 @@ let "bad_oct = 081"
# bad_oct = 081: value too great for base (error token is "081")
# Octal numbers use only digits in the range 0 - 7.
exit 0 # Thanks, Rich Bartell and Stephane Chazelas, for clarification.
exit $? # Thanks, Rich Bartell and Stephane Chazelas, for clarification.
$ sh numbers.sh
$ echo $?
$ 1

View File

@ -15,6 +15,8 @@ Attrib[2]="\"Thirteen Ways of Looking at a Blackbird\""
echo
tput bold # Bold print.
for index in 1 2 3 4 5 # Five lines.
do
printf " %s\n" "${Line[index]}"
@ -25,6 +27,9 @@ do
printf " %s\n" "${Attrib[index]}"
done
tput sgr0 # Reset terminal.
# See 'tput' docs.
echo
exit 0

View File

@ -2,7 +2,7 @@
# pr-ascii.sh: Prints a table of ASCII characters.
START=33 # Range of printable ASCII characters (decimal).
END=125
END=127 # Will not work for unprintable chars. (> 127).
echo " Decimal Hex Character" # Header.
echo " ------- --- ---------"

View File

@ -0,0 +1,39 @@
#!/bin/bash
# primes2.sh
# Generating prime numbers the quick-and-easy way,
#+ without resorting to fancy algorithms.
CEILING=10000 # 1 to 10000
PRIME=0
E_NOTPRIME=
is_prime ()
{
local factors
factors=( $(factor $1) ) # Load output of `factor` into array.
if [ -z "${factors[2]}" ]
# Third element of "factors" array:
#+ ${factors[2]} is 2nd factor of argument.
# If it is blank, then there is no 2nd factor,
#+ and the argument is therefore prime.
then
return $PRIME # 0
else
return $E_NOTPRIME # null
fi
}
echo
for n in $(seq $CEILING)
do
if is_prime $n
then
printf %5d $n
fi # ^ Five positions per number suffices.
done # For a higher $CEILING, adjust upward, as necessary.
echo
exit

View File

@ -0,0 +1,52 @@
#!/bin/bash
# progress-bar.sh
# Author: Dotan Barak (very minor revisions by ABS Guide author).
# Used in ABS Guide with permission (thanks!).
BAR_WIDTH=50
BAR_CHAR_START="["
BAR_CHAR_END="]"
BAR_CHAR_EMPTY="."
BAR_CHAR_FULL="="
BRACKET_CHARS=2
LIMIT=100
print_progress_bar()
{
# Calculate how many characters will be full.
let "full_limit = ((($1 - $BRACKET_CHARS) * $2) / $LIMIT)"
# Calculate how many characters will be empty.
let "empty_limit = ($1 - $BRACKET_CHARS) - ${full_limit}"
# Prepare the bar.
bar_line="${BAR_CHAR_START}"
for ((j=0; j&lt;full_limit; j++)); do
bar_line="${bar_line}${BAR_CHAR_FULL}"
done
for ((j=0; j&lt;empty_limit; j++)); do
bar_line="${bar_line}${BAR_CHAR_EMPTY}"
done
bar_line="${bar_line}${BAR_CHAR_END}"
printf "%3d%% %s" $2 ${bar_line}
}
# Here is a sample of code that uses it.
MAX_PERCENT=100
for ((i=0; i<=MAX_PERCENT; i++)); do
#
usleep 10000
# ... Or run some other commands ...
#
print_progress_bar ${BAR_WIDTH} ${i}
echo -en "\r"
done
echo ""
exit

View File

@ -25,7 +25,7 @@ echo "Q-series [$LIMIT terms]:"
echo -n "${Q[1]} " # Output first two terms.
echo -n "${Q[2]} "
for ((n=3; n <= $LIMIT; n++)) # C-like loop expressions.
for ((n=3; n <= $LIMIT; n++)) # C-like loop expression.
do # Q[n] = Q[n - Q[n-1]] + Q[n - Q[n-2]] for n&gt;2
# Need to break the expression into intermediate terms,
#+ since Bash doesn't handle complex array arithmetic very well.
@ -56,4 +56,4 @@ exit 0
# This is an iterative implementation of the Q-series.
# The more intuitive recursive implementation is left as an exercise.
# Warning: calculating this series recursively takes a VERY long time
#+ via a script. C/C++ would be more suitable.
#+ via a script. C/C++ would be orders of magnitude faster.

View File

@ -460,3 +460,6 @@ exit $?
# 5) Implement "vulnerable" mode of play.
# 6) Improve save-to-file capability (and maybe make it optional).
# 7) Fix bugs!!!
# Reference for more info:
# http://personal.riverusers.com/~thegrendel/qky.README.html

View File

@ -16,12 +16,13 @@ then
exit $E_WRONGARGS
fi
file_excerpt () # Scan file for pattern, then print relevant portion of line.
{
while read line # "while" does not necessarily need "[ condition ]"
do
echo "$line" | grep $1 | awk -F":" '{ print $5 }' # Have awk use ":" delimiter.
done
file_excerpt () # Scan file for pattern,
{ #+ then print relevant portion of line.
while read line # "while" does not necessarily need [ condition ]
do
echo "$line" | grep $1 | awk -F":" '{ print $5 }'
# Have awk use ":" delimiter.
done
} &lt;$file # Redirect into function's stdin.
file_excerpt $pattern

View File

@ -1,6 +1,6 @@
#!/bin/bash
# resistor-inventory.sh
# Simple database application using indirect variable referencing.
# Simple database / table-lookup application.
# ============================================================== #
# Data
@ -18,7 +18,7 @@ B1724_loc=24N
B1724_inventory=243
B1725_value=10000
B1725_powerdissip=.25
B1725_powerdissip=.125
B1725_colorcode="brown-black-orange"
B1725_loc=24N
B1725_inventory=89
@ -42,7 +42,9 @@ do
echo
echo "Catalog number $catalog_number:"
echo "There are ${!Inv} of [${!Val} ohm / ${!Pdissip} watt] resistors in stock."
# Now, retrieve value, using indirect referencing.
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}\"."
@ -57,6 +59,7 @@ echo; echo
# 2) Rewrite this script to use arrays,
#+ rather than indirect variable referencing.
# Which method is more straightforward and intuitive?
# Which method is easier to code?
# Notes:

View File

@ -14,6 +14,7 @@ for element in $(seq 0 $((${#script_contents[@]} - 1)))
# Try changing it to seq 1.
echo -n "${script_contents[$element]}"
# List each field of this script on a single line.
# echo -n "${script_contents[element]}" also works because of ${ ... }.
echo -n " -- " # Use " -- " as a field separator.
done

View File

@ -0,0 +1,117 @@
#!/bin/bash
# sd.sh: Standard Deviation
# The Standard Deviation indicates how consistent a set of data is.
# It shows to what extent the individual data points deviate from the
#+ arithmetic mean, i.e., how much they "bounce around" (or cluster).
# It is essentially the average deviation-distance of the
#+ data points from the mean.
# =========================================================== #
# To calculate the Standard Deviation:
#
# 1 Find the arithmetic mean (average) of all the data points.
# 2 Subtract each data point from the arithmetic mean,
# and square that difference.
# 3 Add all of the individual difference-squares in # 2.
# 4 Divide the sum in # 3 by the number of data points.
# This is known as the "variance."
# 5 The square root of # 4 gives the Standard Deviation.
# =========================================================== #
count=0 # Number of data points; global.
SC=9 # Scale to be used by bc. Nine decimal places.
E_DATAFILE=90 # Data file error.
# ----------------- Set data file ---------------------
if [ ! -z $1 ] # Specify filename as cmd-line arg?
then
datafile="$1" # ASCII text file,
else #+ one (numerical) data point per line!
datafile=sample.dat
fi # See example data file, below.
if [ ! -e "$datafile" ]
then
echo "\""$datafile"\" does not exist!"
exit $E_DATAFILE
fi
# -----------------------------------------------------
arith_mean ()
{
local rt=0 # Running total.
local am=0 # Arithmetic mean.
local ct=0 # Number of data points.
while read value # Read one data point at a time.
do
rt=$(echo "scale=$SC; $rt + $value" | bc)
(( ct++ ))
done
am=$(echo "scale=$SC; $rt / $ct" | bc)
echo $am; return $ct # This function "returns" TWO values!
# Caution: This little trick will not work if $ct > 255!
# To handle a larger number of data points,
#+ simply comment out the "return $ct" above.
} <"$datafile" # Feed in data file.
sd ()
{
mean1=$1 # Arithmetic mean (passed to function).
n=$2 # How many data points.
sum2=0 # Sum of squared differences ("variance").
avg2=0 # Average of $sum2.
sdev=0 # Standard Deviation.
while read value # Read one line at a time.
do
diff=$(echo "scale=$SC; $mean1 - $value" | bc)
# Difference between arith. mean and data point.
dif2=$(echo "scale=$SC; $diff * $diff" | bc) # Squared.
sum2=$(echo "scale=$SC; $sum2 + $dif2" | bc) # Sum of squares.
done
avg2=$(echo "scale=$SC; $sum2 / $n" | bc) # Avg. of sum of squares.
sdev=$(echo "scale=$SC; sqrt($avg2)" | bc) # Square root =
echo $sdev # Standard Deviation.
} <"$datafile" # Rewinds data file.
# ======================================================= #
mean=$(arith_mean); count=$? # Two returns from function!
std_dev=$(sd $mean $count)
echo
echo "Number of data points in \""$datafile"\" = $count"
echo "Arithmetic mean (average) = $mean"
echo "Standard Deviation = $std_dev"
echo
# ======================================================= #
exit
# This script could stand some drastic streamlining,
# but not at the cost of reduced legibility, please.
# ++++++++++++++++++++++++++++++++++++++++ #
# A sample data file (sample1.dat):
# 18.35
# 19.0
# 18.88
# 18.91
# 18.64
# $ sh sd.sh sample1.dat
# Number of data points in "sample1.dat" = 5
# Arithmetic mean (average) = 18.756000000
# Standard Deviation = .235338054
# ++++++++++++++++++++++++++++++++++++++++ #

View File

@ -4,24 +4,20 @@
# Using if [ ... ]
# If a string has not been initialized, it has no defined value.
# This state is called "null" (not the same as zero).
# This state is called "null" (not the same as zero!).
if [ -n $string1 ] # $string1 has not been declared or initialized.
if [ -n $string1 ] # string1 has not been declared or initialized.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# Wrong result.
fi # Wrong result.
# Shows $string1 as not null, although it was not initialized.
echo
# Lets try it again.
# Let's try it again.
if [ -n "$string1" ] # This time, $string1 is quoted.
then
@ -30,51 +26,43 @@ else
echo "String \"string1\" is null."
fi # Quote strings within test brackets!
echo
if [ $string1 ] # This time, $string1 stands naked.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# This works fine.
# The [ ] test operator alone detects whether the string is null.
# However it is good practice to quote it ("$string1").
fi # This works fine.
# The [ ... ] test operator alone detects whether the string is null.
# However it is good practice to quote it (if [ "$string1" ]).
#
# As Stephane Chazelas points out,
# if [ $string1 ] has one argument, "]"
# if [ "$string1" ] has two arguments, the empty "$string1" and "]"
echo
string1=initialized
if [ $string1 ] # Again, $string1 stands naked.
if [ $string1 ] # Again, $string1 stands unquoted.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# Again, gives correct result.
fi # Again, gives correct result.
# Still, it is better to quote it ("$string1"), because . . .
string1="a = b"
if [ $string1 ] # Again, $string1 stands naked.
if [ $string1 ] # Again, $string1 stands unquoted.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# Not quoting "$string1" now gives wrong result!
fi # Not quoting "$string1" now gives wrong result!
exit 0
# Thank you, also, Florian Wisser, for the "heads-up".
exit 0 # Thank you, also, Florian Wisser, for the "heads-up".

View File

@ -5,8 +5,8 @@ String=23skidoo1
# 012345678 Bash
# 123456789 awk
# Note different string indexing system:
# Bash numbers first character of string as '0'.
# Awk numbers first character of string as '1'.
# Bash numbers first character of string as 0.
# Awk numbers first character of string as 1.
echo ${String:2:4} # position 3 (0-1-2), 4 characters long
# skid

View File

@ -1,5 +1,5 @@
#!/bin/bash
# tohtml.sh
# tohtml.sh [v. 0.2, reldate: 06/26/80, still buggy]
# Convert a text file to HTML format.
# Author: Mendel Cooper
@ -96,10 +96,10 @@ process_text ()
# ===================================================
# Convert underscored phrase to italics.
temp=$( echo "$line" |
sed -e 's/ _/ &lt;i&gt;/' -e 's/_ /&lt;\/i&gt; /' |
sed -e 's/^_/&lt;i&gt;/' -e 's/_$/&lt;\/i&gt;/' )
sed -e 's/ _/ &lt;i&gt;/' -e 's/_/&lt;\/i&gt; /' |
sed -e 's/^_/&lt;i&gt;/' -e 's/_/&lt;\/i&gt;/' )
# Process only underscores prefixed by space,
#+ followed by space, or at beginning or end of line.
#+ or at beginning or end of line.
# Do not convert underscores embedded within a word!
line="$temp"
# Slows script execution. Can be optimized?

View File

@ -5,17 +5,17 @@ trap 'echo "VARIABLE-TRACE> \$variable = \"$variable\""' DEBUG
variable=29
echo "Just initialized \"\$variable\" to $variable."
echo " Just initialized \$variable to $variable."
let "variable *= 3"
echo "Just multiplied \"\$variable\" by 3."
echo " Just multiplied \$variable by 3."
exit $?
exit
# The "trap 'command1 . . . command2 . . .' DEBUG" construct is
#+ more appropriate in the context of a complex script,
#+ where placing multiple "echo $variable" statements might be
#+ clumsy and time-consuming.
#+ where inserting multiple "echo $variable" statements might be
#+ awkward and time-consuming.
# Thanks, Stephane Chazelas for the pointer.
@ -24,8 +24,8 @@ Output of script:
VARIABLE-TRACE> $variable = ""
VARIABLE-TRACE> $variable = "29"
Just initialized "$variable" to 29.
Just initialized $variable to 29.
VARIABLE-TRACE> $variable = "29"
VARIABLE-TRACE> $variable = "87"
Just multiplied "$variable" by 3.
Just multiplied $variable by 3.
VARIABLE-TRACE> $variable = "87"

View File

@ -1,6 +1,6 @@
#!/bin/bash
E_WRONG_DIRECTORY=73
E_WRONG_DIRECTORY=83
clear # Clear screen.
@ -23,15 +23,16 @@ rm .[A-Za-z0-9]* # Delete dotfiles.
# (shopt -s dotglob; rm -f *) will also work.
# Thanks, S.C. for pointing this out.
# Filenames may contain all characters in the 0 - 255 range, except "/".
# Deleting files beginning with weird characters is left as an exercise.
# Various other operations here, as necessary.
# A filename (`basename`) may contain all characters in the 0 - 255 range,
#+ except "/".
# Deleting files beginning with weird characters, such as -
#+ is left as an exercise.
echo
echo "Done."
echo "Old files deleted in $TargetDirectory."
echo
# Various other operations here, as necessary.
exit 0
exit $?

View File

@ -28,9 +28,10 @@ fi
MINSTRLEN=3 # Minimum string length.
WORDFILE=/usr/share/dict/linux.words # Dictionary file.
# May specify a different
#+ word list file
#+ of one-word-per-line format.
# May specify a different word list file
#+ of one-word-per-line format.
# For example, the "yawl" word-list package,
# http://personal.riverusers.com/~thegrendel/yawl-0.3.2.tar.gz
wlist=`strings "$1" | tr A-Z a-z | tr '[:space:]' Z | \