mirror of https://github.com/tLDP/LDP
updated
This commit is contained in:
parent
9f7c335603
commit
67d2a75d13
|
@ -7,19 +7,152 @@
|
|||
|
||||
|
||||
==================================================================
|
||||
Current version = 5.6
|
||||
Dated 01/26/09
|
||||
Current version = 6.0.05
|
||||
Dated 03/24/09
|
||||
|
||||
http://bash.neuralshortcircuit.com/abs-guide-latest.tar.bz2
|
||||
http://bash.neuralshortcircuit.com/abs-guide.pdf
|
||||
--------------------------------------------------------------------
|
||||
News: Added Knight's Tour script (ktour.sh),
|
||||
Magic Square script (msquare.sh).
|
||||
--------------------------------------------------------------------
|
||||
Remarks: Gradually adding in-line definitions for technical terms,
|
||||
usually as sidebars, less often as footnotes.
|
||||
News: Major update, version 6.0.
|
||||
Coverage of version 4 of Bash.
|
||||
====================================================================
|
||||
|
||||
Intermediate release
|
||||
Working toward Version 6.1, Buffaloberry release
|
||||
|
||||
1) In "Internal Commands and Builtins" chapter
|
||||
At "eval" entry, reworded intro and added material to first example.
|
||||
|
||||
2) In "External Commands" chapter:
|
||||
In "Math Commands" section:
|
||||
At "dc" entry, added two short usage example, including a
|
||||
somewhat cryptic one (Golden Ratio calculation).
|
||||
|
||||
3) In "Internal Variables" section of "Variables Revisited" chapter:
|
||||
At "$DIRSTACK" entry, added footnote defining "stack."
|
||||
|
||||
4) In "Bash, versions 2, 3, and 4" chapter:
|
||||
In "Bash, version 4" section,
|
||||
Corrected a typo in Substring Extraction entry example script.
|
||||
|
||||
5) In "Bibliography" section:
|
||||
Added entry for Wikipedia article on "dc."
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Version 6.0, Thimbleberry release
|
||||
March 23, 2009
|
||||
|
||||
1) Changed the title of Chapter 1.
|
||||
|
||||
2) Updated "copy-cd.sh" and "ex40.sh" examples
|
||||
to reflect changes in cdrtools.
|
||||
|
||||
3) In "Special Characters" chapter:
|
||||
Added another instance in the "brace expansion" example.
|
||||
|
||||
4) In "Testing and Branching" section of "Loops and Branches" chapter:
|
||||
Clarified outline of "case" construct.
|
||||
|
||||
5) In "Internal Commands and Builtins" chapter:
|
||||
At "eval" entry, added "arr-choice.sh" example script.
|
||||
(Thank you, Antonio Macchi!)
|
||||
At "read" entry, added "-u" option.
|
||||
|
||||
6) In "Internal Variables" section of "Variables Revisited" chapter:
|
||||
Added $BASHPID variable (new to Bash 4+).
|
||||
At "$$" entry, noted that within a subshell, PID of script returned
|
||||
by $$.
|
||||
|
||||
7) In "Arrays" chapter:
|
||||
Added material to "array-function.sh" example script.
|
||||
|
||||
8) In "Variables Revisited" chapter:
|
||||
In "Indirect References" section:
|
||||
Fixed comment in "ind-ref.sh" example, thanks to Jakob Bohm.
|
||||
|
||||
9) In "External Commands" chapter:
|
||||
In "File and Archiving Commands" section:
|
||||
Added "pax" entry.
|
||||
|
||||
10) In "I/O Redirection" chapter:
|
||||
Added a couple of new instances on stderr redirection.
|
||||
Added comments on a couple of new operators added in ver. 4 of Bash
|
||||
that are still not functional.
|
||||
|
||||
11) In "Bash, versions 2, 3, and 4" chapter (new title!):
|
||||
In Version 3 section, more on quoting "=~" operator.
|
||||
Added instances in "brace expansion" example.
|
||||
|
||||
Added a section for version 4 of Bash.
|
||||
Added "fetch_address.sh" and "fetch_address-2.sh" examples
|
||||
to illustrate associative arrays.
|
||||
Added "cas4.sh" example to illustrate enhancements to case construct.
|
||||
Added discussion of the new "coproc" command, with illustrative
|
||||
examples.
|
||||
Added discussion of the new "mapfile" command, with an illustrative
|
||||
example.
|
||||
Briefly mentioned a couple of the changes to "read" options.
|
||||
Listed the new -l and -c options to "declare" builtin,
|
||||
with a short illustrated inline script.
|
||||
Listed new upper/lowercase operators for parameter substitution,
|
||||
with example.
|
||||
Listed the new "brace expansion" options.
|
||||
Discussed change in the treatment of positional parameters
|
||||
in substring extraction.
|
||||
Discussed the new ** globbing operator and "globstar" shell option.
|
||||
Discussed the new "command_not_found_handle ()" error-handling
|
||||
function, with in-line example.
|
||||
Added an "editorial" sidebar. It is certain to generate controversy.
|
||||
|
||||
12) In "System Resources" subsection of "System and Administrative
|
||||
At "ulimit" entry, added footnote about -f, -c behavior in POSIX
|
||||
mode and newly-added options (ver. 4+ of Bash).
|
||||
|
||||
13) In "Process Substitution" chapter:
|
||||
Added "wr-ps.bash" while-read loop example.
|
||||
(Thank you, Tomas Pospisek!)
|
||||
|
||||
14) In "Gotchas" chapter:
|
||||
Samuli Kaipiainen supplied a corrected explanation for piping-to-grep
|
||||
misbehavior.
|
||||
|
||||
15) In the "Portability Issues" section of the "Miscellany" chapter:
|
||||
Added entries to list of features in Bash missing in traditional "sh."
|
||||
|
||||
16) In "Options" chapter:
|
||||
Added entries for "globstar" and "checkjobs" in the table.
|
||||
|
||||
17) In "Subshells" chapter:
|
||||
Added a few comments and a short in-line example.
|
||||
|
||||
18) In "Contributed Scripts" appendix:
|
||||
Added "fifteen.sh" (Fifteen Puzzle) example script.
|
||||
(Thank you, Antonio Macchi!)
|
||||
Added "hanoi2.bash" -- graphic version of "hanoi.bash."
|
||||
Added "hanoi2a.bash" -- alternate graphic version of "hanoi.bash."
|
||||
Had to remove "obj-oriented.sh" example because it only works
|
||||
with obsolete versions of Bash.
|
||||
Removed "ftpget.sh" script.
|
||||
|
||||
19) In "Download and Mirror Sites" appendix:
|
||||
Fixed a typo in the ABS Guide download URL.
|
||||
|
||||
20) In "Bibliography" section:
|
||||
Added Shell Script Games entry.
|
||||
Added Bash Hackers Wiki entry.
|
||||
Added mirror site for the official Bash FAQ.
|
||||
Added Greg's WIKI: Bash FAQ entry.
|
||||
Added joyent site.
|
||||
|
||||
21) Updated the Index with references to new material.
|
||||
|
||||
22) Numberous syntactical and stylistic fixes.
|
||||
|
||||
|
||||
|
||||
Version 5.6, Worcesterberry release
|
||||
01/26/09
|
||||
|
||||
|
|
|
@ -11,9 +11,23 @@
|
|||
|
||||
<!-- Characters and symbols -->
|
||||
<para><command>^ </command> (caret)
|
||||
<link linkend="beglineref">Beginning-of-line</link>, in a <link
|
||||
linkend="regexref">Regular Expression</link></para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<link linkend="beglineref">Beginning-of-line</link>,
|
||||
in a <link linkend="regexref">Regular Expression</link>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>^</command></para>
|
||||
<para><command>^^</command></para>
|
||||
<para><link linkend="casemodparamsub">Uppercase
|
||||
conversion</link> in <firstterm>parameter
|
||||
substitution</firstterm></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para><command>~ </command> <firstterm>Tilde</firstterm>
|
||||
<itemizedlist>
|
||||
|
@ -233,9 +247,8 @@
|
|||
command</para></listitem>
|
||||
<listitem><para><command>;; </command>
|
||||
<link linkend="doublesemicolon">Double-semicolon</link>, terminator in a
|
||||
<link linkend="caseesac1">case</link> option</para></listitem>
|
||||
<link linkend="caseesac1">case</link> option</para>
|
||||
|
||||
<listitem>
|
||||
<para>Required when ...</para>
|
||||
<para><link linkend="needsemicolon"><firstterm>do</firstterm>
|
||||
keyword is on the first line of
|
||||
|
@ -245,6 +258,11 @@
|
|||
code block</link></para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para><command>;;&</command> <command>;&</command>
|
||||
<link linkend="ncterm">Terminators</link> in
|
||||
a <firstterm>case</firstterm> option (<link
|
||||
linkend="bash4ref">version 4+</link> of Bash).</para></listitem>
|
||||
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><command>: </command>
|
||||
|
@ -342,7 +360,19 @@
|
|||
quoting</link></para>
|
||||
|
||||
<para><command>,</command>
|
||||
<link linkend="commaop">Comma operator</link></para>
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
<link linkend="commaop">Comma operator</link>
|
||||
</para></listitem>
|
||||
<listitem>
|
||||
<para><command>,</command></para>
|
||||
<para><command>,,</command></para>
|
||||
<para><link linkend="casemodparamsub">Lowercase
|
||||
conversion</link> in <firstterm>parameter
|
||||
substitution</firstterm></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ********************** -->
|
||||
|
@ -618,6 +648,12 @@
|
|||
arithmetic operator
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<command> ** </command>
|
||||
Extended <firstterm>globbing</firstterm>
|
||||
<link linkend="globstarref">file-match operator</link>
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<!-- ********************** -->
|
||||
|
@ -769,6 +805,8 @@
|
|||
|
||||
<para><link linkend="arrayref">Arrays</link></para>
|
||||
<itemizedlist>
|
||||
<listitem><para><link linkend="assocarr">Associative arrays</link>
|
||||
</para></listitem>
|
||||
<listitem><para><link linkend="arrayref">Bracket notation</link>
|
||||
</para></listitem>
|
||||
<listitem><para><link linkend="arrayappend0">Concatenating</link>,
|
||||
|
@ -881,6 +919,8 @@
|
|||
Version 2</link></para></listitem>
|
||||
<listitem><para><link linkend="bash3ref">
|
||||
Version 3</link></para></listitem>
|
||||
<listitem><para><link linkend="bash4ref">
|
||||
Version 4</link></para></listitem>
|
||||
|
||||
</itemizedlist></para>
|
||||
<!-- ********************** -->
|
||||
|
@ -931,6 +971,10 @@
|
|||
<listitem><para><link
|
||||
linkend="braceexpref33">Extended</link>,
|
||||
<replaceable>{a..z}</replaceable></para></listitem>
|
||||
<listitem><para>With <link
|
||||
linkend="braceexpref4">increment and
|
||||
zero-padding</link> (new feature in Bash, <link linkend="bash4ref">version
|
||||
4</link>)</para></listitem>
|
||||
</itemizedlist></para>
|
||||
<!-- ********************** -->
|
||||
|
||||
|
@ -1029,6 +1073,10 @@
|
|||
|
||||
<para><link linkend="bash-options">Command-line options</link></para>
|
||||
|
||||
<para><link linkend="cnfh">command_not_found_handle ()</link>
|
||||
<firstterm>builtin</firstterm> error-handling function
|
||||
(<link linkend="bash4ref">version 4+</link> of Bash)</para>
|
||||
|
||||
<para><link linkend="commandsubref">Command substitution</link>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
|
@ -1100,6 +1148,7 @@
|
|||
</itemizedlist></para>
|
||||
<!-- ***************************************************************** -->
|
||||
|
||||
<para><link linkend="coprocref">Coprocesses</link></para>
|
||||
<para><link linkend="cronref">cron</link>, scheduling
|
||||
<firstterm>daemon</firstterm></para>
|
||||
<para><link linkend="cstyle"><firstterm>C</firstterm>-style syntax
|
||||
|
@ -1167,8 +1216,11 @@
|
|||
|
||||
<para><link linkend="declare1ref">declare</link> builtin</para>
|
||||
<itemizedlist>
|
||||
<listitem><para><link
|
||||
linkend="declareopsref1">options</link></para></listitem>
|
||||
<listitem>
|
||||
<para><link linkend="declareopsref1">options</link></para>
|
||||
<para><link linkend="declarecasemod">case-modification</link>
|
||||
options (<link linkend="bash4ref">version 4+</link> of Bash)
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><link linkend="defparam">Default parameters</link></para>
|
||||
|
@ -1285,6 +1337,9 @@
|
|||
references</link></para></listitem>
|
||||
<listitem><para><link linkend="evalrisk">Risk of
|
||||
using</link></para></listitem>
|
||||
<listitem><para><link linkend="arrchoice0">Using
|
||||
<firstterm>eval</firstterm> to select among
|
||||
variables</link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="dblbraev">Evaluation of
|
||||
|
@ -1496,6 +1551,8 @@
|
|||
linkend="cryptoquote">Crypto-Quotes</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="cards">Dealing a deck of cards</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="fifteen">Fifteen Puzzle</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="horserace">Horse race</link></para></listitem>
|
||||
<listitem><para><link
|
||||
|
@ -1517,7 +1574,12 @@
|
|||
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>
|
||||
linkend="hanoi">Towers of Hanoi</link></para>
|
||||
<para><link linkend="hanoi2">Graphic
|
||||
version</link></para>
|
||||
<para><link linkend="hanoi2a">Alternate graphic
|
||||
version</link></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="getopty">getopt</link>,
|
||||
|
@ -1549,6 +1611,9 @@
|
|||
<filename>dot files</filename></link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="goldenratio">Golden Ratio</link>
|
||||
(<firstterm>Phi</firstterm>)</para>
|
||||
|
||||
<para><link linkend="ge0ref"> -ge </link>,
|
||||
<firstterm>greater-than or equal</firstterm>
|
||||
<link linkend="icomparison1">integer comparison</link> test</para>
|
||||
|
@ -1608,6 +1673,8 @@
|
|||
<para><link
|
||||
linkend="herestringsref"><firstterm>Here</firstterm>
|
||||
strings</link></para>
|
||||
<para>Calculating the <link linkend="goldenratio">Golden
|
||||
Ratio</link></para>
|
||||
<para><link linkend="hspre">Prepending text</link></para>
|
||||
<para><link linkend="hsread">Using
|
||||
<firstterm>read</firstterm></link></para>
|
||||
|
@ -1911,6 +1978,8 @@
|
|||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para><link linkend="mapfileref">mapfile</link> builtin,
|
||||
loads an array with a text file</para>
|
||||
<para><link linkend="mathc">Math commands</link></para>
|
||||
<para><link linkend="metameaningref">Meta-meaning</link></para>
|
||||
|
||||
|
@ -2019,6 +2088,11 @@
|
|||
<firstterm>parameter</firstterm></link></para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para><link linkend="casemodparamsub">
|
||||
<firstterm>Case modification</firstterm></link>
|
||||
(<link linkend="bash4ref">version 4+</link> of
|
||||
Bash).</para></listitem>
|
||||
|
||||
<listitem><para><link linkend="pw0"><firstterm>Script
|
||||
example</firstterm></link></para></listitem>
|
||||
<listitem><para><link linkend="parsubtab"><command>Table</command></link>
|
||||
|
@ -2161,7 +2235,9 @@
|
|||
<para><link linkend="pipeloop"><firstterm>echo</firstterm>
|
||||
to a loop</link></para>
|
||||
<para><link linkend="badread0"><firstterm>echo</firstterm>
|
||||
to <firstterm>read</firstterm></link></para>
|
||||
to <firstterm>read</firstterm></link> (however, this problem
|
||||
<link linkend="goodread0">can be circumvented</link>)</para>
|
||||
|
||||
<para><link linkend="ptailgrep"><firstterm>tail</firstterm>
|
||||
<option>-f</option> to <firstterm>grep</firstterm></link></para>
|
||||
</listitem>
|
||||
|
@ -2180,6 +2256,9 @@
|
|||
<listitem><para><link linkend="varsubsh">Variables in a
|
||||
<firstterm>subshell</firstterm></link>, <firstterm>scope</firstterm>
|
||||
limited</para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="badread0">Subshell in <firstterm>while-read</firstterm>
|
||||
loop</link></para></listitem>
|
||||
<listitem><para><link linkend="wsbad">Whitespace</link>,
|
||||
misuse of</para></listitem>
|
||||
|
||||
|
@ -2297,6 +2376,10 @@
|
|||
command</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="commandsparens1">Template</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="goodread0"><firstterm>while-read</firstterm> loop
|
||||
without a
|
||||
<firstterm>subshell</firstterm></link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
<!-- *************************************************************** -->
|
||||
<para>Prompt
|
||||
|
@ -2427,6 +2510,8 @@
|
|||
construct</para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="readlineref">readline</link> library</para>
|
||||
|
||||
<para><link linkend="recursionref">Recursion</link>
|
||||
<itemizedlist>
|
||||
<listitem><para><link
|
||||
|
@ -2713,9 +2798,15 @@
|
|||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="scharlist1">Special characters</link></para>
|
||||
<para>Stack, emulating a push-down, <link
|
||||
linkend="stackex0"><firstterm>example
|
||||
script</firstterm></link></para>
|
||||
|
||||
<para>Stack
|
||||
<itemizedlist>
|
||||
<listitem><para><link
|
||||
linkend="stackdefref">Definition</link></para></listitem>
|
||||
<listitem><para>Emulating a <firstterm>push-down stack</firstterm>,
|
||||
<link linkend="stackex0">example script</link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>Standard Deviation, <link linkend="stddev">example script</link></para>
|
||||
<para><link linkend="filesref1">Startup files</link>, Bash</para>
|
||||
|
||||
|
@ -3089,7 +3180,12 @@
|
|||
<listitem><para><link linkend="intparam">Testing a variable</link>
|
||||
to see if it contains only digits</para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="trackingscr">Tracking script usage</link></para></listitem>
|
||||
linkend="trackingscr">Tracking script
|
||||
usage</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="goodread0"><firstterm>while-read</firstterm> loop
|
||||
without a
|
||||
<firstterm>subshell</firstterm></link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="widgetref">Widgets</link>, invoking from a
|
||||
script</para></listitem>
|
||||
|
@ -3288,9 +3384,14 @@
|
|||
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>
|
||||
<listitem>
|
||||
<para><link linkend="whilereadref2">
|
||||
<firstterm>while read</firstterm></link>
|
||||
construct
|
||||
</para>
|
||||
<para><link linkend="goodread0">Avoiding a
|
||||
<firstterm>subshell</firstterm></link></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="whitespaceref">Whitespace</link>,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
# arr-choice.sh
|
||||
|
||||
# Passing arguments to a function to select
|
||||
#+ one particular variable out of a group.
|
||||
|
||||
arr0=( 10 11 12 13 14 15 )
|
||||
arr1=( 20 21 22 23 24 25 )
|
||||
arr2=( 30 31 32 33 34 35 )
|
||||
# 0 1 2 3 4 5 Element number (zero-indexed)
|
||||
|
||||
|
||||
choose_array ()
|
||||
{
|
||||
eval array_member=\${arr${array_number}[element_number]}
|
||||
# ^ ^^^^^^^^^^^^
|
||||
# Using eval to construct the name of a variable,
|
||||
#+ in this particular case, an array name.
|
||||
|
||||
echo "Element $element_number of array $array_number is $array_member"
|
||||
} # Function can be rewritten to take parameters.
|
||||
|
||||
array_number=0 # First array.
|
||||
element_number=3
|
||||
choose_array # 13
|
||||
|
||||
array_number=2 # Third array.
|
||||
element_number=4
|
||||
choose_array # 34
|
||||
|
||||
array_number=3 # Null array (arr3 not allocated).
|
||||
element_number=4
|
||||
choose_array # (null)
|
||||
|
||||
# Thank you, Antonio Macchi, for pointing this out.
|
|
@ -51,4 +51,25 @@ echo "Passed array (within function) = ${passed_array[@]}"
|
|||
|
||||
echo
|
||||
|
||||
############################################
|
||||
|
||||
# And here is an even more explicit example:
|
||||
|
||||
ret_array ()
|
||||
{
|
||||
for element in {11..20}
|
||||
do
|
||||
echo "$element " # Echo individual elements
|
||||
done #+ of what will be assembled into an array.
|
||||
}
|
||||
|
||||
arr=( $(ret_array) ) # Assemble into array.
|
||||
|
||||
echo "Capturing array \"arr\" from function ret_array () ..."
|
||||
echo "Third element of array \"arr\" is ${arr[2]}." # 13 (zero-indexed)
|
||||
echo -n "Entire array is: "
|
||||
echo ${arr[@]} # 11 12 13 14 15 16 17 18 19 20
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -74,10 +74,10 @@ declare -a ArrayVar
|
|||
|
||||
|
||||
|
||||
# The echo command is a built-in.
|
||||
# The echo command is a builtin.
|
||||
echo $VarSomething
|
||||
|
||||
# The printf command is a built-in.
|
||||
# The printf command is a builtin.
|
||||
# Translate %s as: String-Format
|
||||
printf %s $VarSomething # No linebreak specified, none output.
|
||||
echo # Default, only linebreak output.
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Strips off the header from a mail/News message i.e. till the first
|
||||
# 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.
|
||||
|
||||
|
@ -19,7 +18,33 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
exit
|
||||
|
||||
# ==> Exercise: Add error checking and other options.
|
||||
# ==>
|
||||
# ==> Note that the small sed script repeats, except for the arg passed.
|
||||
# ==> Does it make sense to embed it in a function? Why or why not?
|
||||
|
||||
|
||||
/*
|
||||
* Copyright University of Toronto 1988, 1989.
|
||||
* Written by Mark Moraes
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose on
|
||||
* any computer system, and to alter it and redistribute it freely, subject
|
||||
* to the following restrictions:
|
||||
*
|
||||
* 1. The author and the University of Toronto are not responsible
|
||||
* for the consequences of use of this software, no matter how awful,
|
||||
* even if they arise from flaws in it.
|
||||
*
|
||||
* 2. The origin of this software must not be misrepresented, either by
|
||||
* explicit claim or by omission. Since few users ever read sources,
|
||||
* credits must appear in the documentation.
|
||||
*
|
||||
* 3. Altered versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software. Since few users
|
||||
* ever read sources, credits must appear in the documentation.
|
||||
*
|
||||
* 4. This notice may not be removed or altered.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash4
|
||||
|
||||
test_char ()
|
||||
{
|
||||
case "$1" in
|
||||
[[:print:]] ) echo "$1 is a printable character.";;& # |
|
||||
# The ;;& terminator continues to the next pattern test. |
|
||||
[[:alnum:]] ) echo "$1 is an alpha/numeric character.";;& # v
|
||||
[[:alpha:]] ) echo "$1 is an alphabetic character.";;& # v
|
||||
[[:lower:]] ) echo "$1 is a lowercase alphabetic character.";;&
|
||||
[[:digit:]] ) echo "$1 is an numeric character.";& # |
|
||||
# The ;& terminator executes the next statement ... # |
|
||||
%%%@@@@@ ) echo "********************************";; # v
|
||||
# ^^^^^^^^ ... even with a dummy pattern.
|
||||
esac
|
||||
}
|
||||
|
||||
echo
|
||||
|
||||
test_char 3
|
||||
# 3 is a printable character.
|
||||
# 3 is an alpha/numeric character.
|
||||
# 3 is an numeric character.
|
||||
# ********************************
|
||||
echo
|
||||
|
||||
test_char m
|
||||
# m is a printable character.
|
||||
# m is an alpha/numeric character.
|
||||
# m is an alphabetic character.
|
||||
# m is a lowercase alphabetic character.
|
||||
echo
|
||||
|
||||
test_char /
|
||||
# / is a printable character.
|
||||
|
||||
echo
|
||||
|
||||
# The ;;& terminator can save complex if/then conditions.
|
||||
# The ;& is somewhat less useful.
|
|
@ -5,9 +5,9 @@ CDROM=/dev/cdrom # CD ROM device
|
|||
OF=/home/bozo/projects/cdimage.iso # output file
|
||||
# /xxxx/xxxxxxxx/ Change to suit your system.
|
||||
BLOCKSIZE=2048
|
||||
SPEED=10 # May use higher speed ...
|
||||
DEVICE=/dev/cdrom
|
||||
# DEVICE="0,0" on older versions of cdrecord.
|
||||
# SPEED=10 # If unspecified, uses max spd.
|
||||
# DEVICE=/dev/cdrom older version.
|
||||
DEVICE="1,0,0"
|
||||
|
||||
echo; echo "Insert source CD, but do *not* mount it."
|
||||
echo "Press ENTER when ready. "
|
||||
|
@ -26,7 +26,8 @@ read ready # Wait for input, $ready not used.
|
|||
|
||||
echo "Copying $OF to CDR."
|
||||
|
||||
cdrecord -v -isosize speed=$SPEED dev=$DEVICE $OF
|
||||
# cdrecord -v -isosize speed=$SPEED dev=$DEVICE $OF # Old version.
|
||||
wodim -v -isosize dev=$DEVICE $OF
|
||||
# Uses Joerg Schilling's "cdrecord" package (see its docs).
|
||||
# http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html
|
||||
# Newer Linux distros may use "wodim" rather than "cdrecord" ...
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
SPEED=10 # May use higher speed if your hardware supports it.
|
||||
IMAGEFILE=cdimage.iso
|
||||
CONTENTSFILE=contents
|
||||
DEVICE=/dev/cdrom
|
||||
# DEVICE="0,0" For older versions of cdrecord
|
||||
# DEVICE=/dev/cdrom For older versions of cdrecord
|
||||
DEVICE="1,0,0"
|
||||
DEFAULTDIR=/opt # This is the directory containing the data to be burned.
|
||||
# Make sure it exists.
|
||||
# Exercise: Add a test for this.
|
||||
|
@ -41,8 +41,10 @@ echo "Creating ISO9660 file system image ($IMAGEFILE)."
|
|||
# Burn the CDR.
|
||||
echo "Burning the disk."
|
||||
echo "Please be patient, this will take a while."
|
||||
cdrecord -v -isosize speed=$SPEED dev=$DEVICE $IMAGEFILE
|
||||
# In newer Linux distros, the "wodim" utility may assume the
|
||||
wodim -v -isosize dev=$DEVICE $IMAGEFILE
|
||||
# In newer Linux distros, the "wodim" utility assumes the
|
||||
#+ functionality of "cdrecord."
|
||||
exitcode=$?
|
||||
echo "Exit code = $exitcode"
|
||||
|
||||
exit $?
|
||||
exit $exitcode
|
||||
|
|
|
@ -29,7 +29,8 @@ Password="your.e-mail.address" # Change above to suit.
|
|||
ftp -n $Server <<End-Of-Session
|
||||
# -n option disables auto-logon
|
||||
|
||||
user anonymous "$Password"
|
||||
user anonymous "$Password" # If this doesn't work, then try:
|
||||
# quote user anonymous "$Password"
|
||||
binary
|
||||
bell # Ring 'bell' after each file transfer.
|
||||
cd $Directory
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash4
|
||||
# fetch_address-2.sh
|
||||
# A more elaborate version of fetch_address.sh.
|
||||
|
||||
SUCCESS=0
|
||||
E_DB=99 # Error code for missing entry.
|
||||
|
||||
declare -A address
|
||||
# -A option declares associative array.
|
||||
|
||||
|
||||
store_address ()
|
||||
{
|
||||
address[$1]="$2"
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
fetch_address ()
|
||||
{
|
||||
if [[ -z "${address[$1]}" ]]
|
||||
then
|
||||
echo "$1's address is not in database."
|
||||
return $E_DB
|
||||
fi
|
||||
|
||||
echo "$1's address is ${address[$1]}."
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
store_address "Charles Jones" "414 W. 10th Ave., Baltimore, MD 21236"
|
||||
store_address "John Smith" "202 E. 3rd St., New York, NY 10009"
|
||||
store_address "Wilma Wilson" "1854 Vermont Ave, Los Angeles, CA 90023"
|
||||
# Exercise:
|
||||
# Rewrite the above store_address calls to read data from a file,
|
||||
#+ then assign field 1 to name, field 2 to address in the array.
|
||||
# Each line in the file would have a format corresponding to the above.
|
||||
# Use a while-read loop to read from file, sed or awk to parse the fields.
|
||||
|
||||
fetch_address "Charles Jones"
|
||||
# Charles Jones's address is 414 W. 10th Ave., Baltimore, MD 21236.
|
||||
fetch_address "Wilma Wilson"
|
||||
# Wilma Wilson's address is 1854 Vermont Ave, Los Angeles, CA 90023.
|
||||
fetch_address "John Smith"
|
||||
# John Smith's address is 202 E. 3rd St., New York, NY 10009.
|
||||
fetch_address "Bozo Bozeman"
|
||||
# Bozo Bozeman's address is not in database.
|
||||
|
||||
exit $? # In this case, exit code = 99, since that is function return.
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash4
|
||||
# fetch_address.sh
|
||||
|
||||
declare -A address
|
||||
# -A option declares associative array.
|
||||
|
||||
address[Charles]="414 W. 10th Ave., Baltimore, MD 21236"
|
||||
address[John]="202 E. 3rd St., New York, NY 10009"
|
||||
address[Wilma]="1854 Vermont Ave, Los Angeles, CA 90023"
|
||||
|
||||
|
||||
echo "Charles's address is ${address[Charles]}."
|
||||
# Charles's address is 414 W. 10th Ave., Baltimore, MD 21236.
|
||||
echo "Wilma's address is ${address[Wilma]}."
|
||||
# Wilma's address is 1854 Vermont Ave, Los Angeles, CA 90023.
|
||||
echo "John's address is ${address[John]}."
|
||||
# John's address is 202 E. 3rd St., New York, NY 10009.
|
|
@ -0,0 +1,173 @@
|
|||
#!/bin/bash
|
||||
# fifteen.sh
|
||||
|
||||
# Classic "Fifteen Puzzle"
|
||||
# Author: Antonio Macchi
|
||||
# Lightly edited and commented by ABS Guide author.
|
||||
# Used in ABS Guide with permission. (Thanks!)
|
||||
|
||||
# The invention of the Fifteen Puzzle is attributed to either
|
||||
#+ Sam Loyd or Noyes Palmer Chapman.
|
||||
# The puzzle was wildly popular in the late 19th-century.
|
||||
|
||||
# Object: Rearrange the numbers so they read in order,
|
||||
#+ from 1 - 15: ________________
|
||||
# | 1 2 3 4 |
|
||||
# | 5 6 7 8 |
|
||||
# | 9 10 11 12 |
|
||||
# | 13 14 15 |
|
||||
# ----------------
|
||||
|
||||
|
||||
#######################
|
||||
# Constants #
|
||||
SQUARES=16 #
|
||||
FAIL=70 #
|
||||
E_PREMATURE_EXIT=80 #
|
||||
#######################
|
||||
|
||||
|
||||
########
|
||||
# Data #
|
||||
########
|
||||
|
||||
Puzzle=( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " " )
|
||||
|
||||
|
||||
#############
|
||||
# Functions #
|
||||
#############
|
||||
|
||||
function swap
|
||||
{
|
||||
local tmp
|
||||
|
||||
tmp=${Puzzle[$1]}
|
||||
Puzzle[$1]=${Puzzle[$2]}
|
||||
Puzzle[$2]=$tmp
|
||||
}
|
||||
|
||||
|
||||
function Jumble
|
||||
{ # Scramble the pieces at beginning of round.
|
||||
local i pos1 pos2
|
||||
|
||||
for i in {1..100}
|
||||
do
|
||||
pos1=$(( $RANDOM % $SQUARES))
|
||||
pos2=$(( $RANDOM % $SQUARES ))
|
||||
swap $pos1 $pos2
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function PrintPuzzle
|
||||
{
|
||||
local i1 i2 puzpos
|
||||
puzpos=0
|
||||
|
||||
clear
|
||||
echo "Enter quit to exit."; echo # Better that than Ctl-C.
|
||||
|
||||
echo ",----.----.----.----." # Top border.
|
||||
for i1 in {1..4}
|
||||
do
|
||||
for i2 in {1..4}
|
||||
do
|
||||
printf "| %2s " "${Puzzle[$puzpos]}"
|
||||
(( puzpos++ ))
|
||||
done
|
||||
echo "|" # Right-side border.
|
||||
test $i1 = 4 || echo "+----+----+----+----+"
|
||||
done
|
||||
echo "'----'----'----'----'" # Bottom border.
|
||||
}
|
||||
|
||||
|
||||
function GetNum
|
||||
{ # Test for valid input.
|
||||
local puznum garbage
|
||||
|
||||
while true
|
||||
do
|
||||
echo "Moves: $moves" # Also counts invalid moves.
|
||||
read -p "Number to move: " puznum garbage
|
||||
if [ "$puznum" = "quit" ]; then echo; exit $E_PREMATURE_EXIT; fi
|
||||
test -z "$puznum" -o -n "${puznum//[0-9]/}" && continue
|
||||
test $puznum -gt 0 -a $puznum -lt $SQUARES && break
|
||||
done
|
||||
return $puznum
|
||||
}
|
||||
|
||||
|
||||
function GetPosFromNum
|
||||
{ # $1 = puzzle-number
|
||||
local puzpos
|
||||
|
||||
for puzpos in {0..15}
|
||||
do
|
||||
test "${Puzzle[$puzpos]}" = "$1" && break
|
||||
done
|
||||
return $puzpos
|
||||
}
|
||||
|
||||
|
||||
function Move
|
||||
{ # $1=Puzzle-pos
|
||||
test $1 -gt 3 && test "${Puzzle[$(( $1 - 4 ))]}" = " "\
|
||||
&& swap $1 $(( $1 - 4 )) && return 0
|
||||
test $(( $1%4 )) -ne 3 && test "${Puzzle[$(( $1 + 1 ))]}" = " "\
|
||||
&& swap $1 $(( $1 + 1 )) && return 0
|
||||
test $1 -lt 12 && test "${Puzzle[$(( $1 + 4 ))]}" = " "\
|
||||
&& swap $1 $(( $1 + 4 )) && return 0
|
||||
test $(( $1%4 )) -ne 0 && test "${Puzzle[$(( $1 - 1 ))]}" = " " &&\
|
||||
swap $1 $(( $1 - 1 )) && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
function Solved
|
||||
{
|
||||
local pos
|
||||
|
||||
for pos in {0..14}
|
||||
do
|
||||
test "${Puzzle[$pos]}" = $(( $pos + 1 )) || return $FAIL
|
||||
# Check whether number in each square = square number.
|
||||
done
|
||||
return 0 # Successful solution.
|
||||
}
|
||||
|
||||
|
||||
################### MAIN () ########################
|
||||
moves=0
|
||||
Jumble
|
||||
|
||||
while true # Loop continuously until puzzle solved.
|
||||
do
|
||||
echo; echo
|
||||
PrintPuzzle
|
||||
echo
|
||||
while true
|
||||
do
|
||||
GetNum
|
||||
puznum=$?
|
||||
GetPosFromNum $puznum
|
||||
puzpos=$?
|
||||
((moves++))
|
||||
Move $puzpos && break
|
||||
done
|
||||
Solved && break
|
||||
done
|
||||
|
||||
echo;echo
|
||||
PrintPuzzle
|
||||
echo; echo "BRAVO!"; echo
|
||||
|
||||
exit 0
|
||||
####################################################
|
||||
|
||||
# Exercise:
|
||||
# --------
|
||||
# Rewrite the script to display the letters A - O,
|
||||
#+ rather than the numbers 1 - 15.
|
|
@ -0,0 +1,202 @@
|
|||
#! /bin/bash
|
||||
# The Towers Of Hanoi
|
||||
# Original script (hanoi.bash) copyright (C) 2000 Amit Singh.
|
||||
# All Rights Reserved.
|
||||
# http://hanoi.kernelthread.com
|
||||
|
||||
# hanoi2.bash
|
||||
# Version 2: modded for ASCII-graphic display.
|
||||
# Uses code contributed by Antonio Macchi,
|
||||
#+ with heavy editing by ABS Guide author.
|
||||
# This variant also falls under the original copyright, see above.
|
||||
# Used in ABS Guide with Amit Singh's permission (thanks!).
|
||||
|
||||
|
||||
# Variables #
|
||||
E_NOPARAM=86
|
||||
E_BADPARAM=87 # Illegal no. of disks passed to script.
|
||||
E_NOEXIT=88
|
||||
DISKS=$1
|
||||
Moves=0
|
||||
|
||||
MWIDTH=7
|
||||
MARGIN=2
|
||||
# Arbitrary "magic" constants, work okay for relatively small # of disks.
|
||||
# BASEWIDTH=51 # Original code.
|
||||
let "basewidth = $MWIDTH * $DISKS + $MARGIN" # "Base" beneath rods.
|
||||
# Above "algorithm" could likely stand improvement.
|
||||
|
||||
# Display variables.
|
||||
let "disks1 = $DISKS - 1"
|
||||
let "spaces1 = $DISKS"
|
||||
let "spaces2 = 2 * $DISKS"
|
||||
|
||||
let "lastmove_t = $DISKS - 1" # Final move?
|
||||
|
||||
|
||||
declare -a Rod1 Rod2 Rod3
|
||||
|
||||
#################
|
||||
|
||||
|
||||
function repeat { # $1=char $2=number of repetitions
|
||||
local n # Repeat-print a character.
|
||||
|
||||
for (( n=0; n<$2; n++ )); do
|
||||
echo -n "$1"
|
||||
done
|
||||
}
|
||||
|
||||
function FromRod {
|
||||
local rod summit weight sequence
|
||||
|
||||
while true; do
|
||||
rod=$1
|
||||
test ${rod/[^123]/} || continue
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for summit in $sequence; do
|
||||
eval weight=\${Rod${rod}[$summit]}
|
||||
test $weight -ne 0 &&
|
||||
{ echo "$rod $summit $weight"; return; }
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function ToRod { # $1=previous (FromRod) weight
|
||||
local rod firstfree weight sequence
|
||||
|
||||
while true; do
|
||||
rod=$2
|
||||
test ${rod/[^123]} || continue
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for firstfree in $sequence; do
|
||||
eval weight=\${Rod${rod}[$firstfree]}
|
||||
test $weight -gt 0 && { (( firstfree++ )); break; }
|
||||
done
|
||||
test $weight -gt $1 -o $firstfree = 0 &&
|
||||
{ echo "$rod $firstfree"; return; }
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function PrintRods {
|
||||
local disk rod empty fill sp sequence
|
||||
|
||||
|
||||
repeat " " $spaces1
|
||||
echo -n "|"
|
||||
repeat " " $spaces2
|
||||
echo -n "|"
|
||||
repeat " " $spaces2
|
||||
echo "|"
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for disk in $sequence; do
|
||||
for rod in {1..3}; do
|
||||
eval empty=$(( $DISKS - (Rod${rod}[$disk] / 2) ))
|
||||
eval fill=\${Rod${rod}[$disk]}
|
||||
repeat " " $empty
|
||||
test $fill -gt 0 && repeat "*" $fill || echo -n "|"
|
||||
repeat " " $empty
|
||||
done
|
||||
echo
|
||||
done
|
||||
repeat "=" $basewidth # Print "base" beneath rods.
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
display ()
|
||||
{
|
||||
echo
|
||||
PrintRods
|
||||
|
||||
# Get rod-number, summit and weight
|
||||
first=( `FromRod $1` )
|
||||
eval Rod${first[0]}[${first[1]}]=0
|
||||
|
||||
# Get rod-number and first-free position
|
||||
second=( `ToRod ${first[2]} $2` )
|
||||
eval Rod${second[0]}[${second[1]}]=${first[2]}
|
||||
|
||||
|
||||
echo; echo; echo
|
||||
if [ "${Rod3[lastmove_t]}" = 1 ]
|
||||
then # Last move? If yes, then display final position.
|
||||
echo "+ Final Position: $Moves moves"; echo
|
||||
PrintRods
|
||||
fi
|
||||
}
|
||||
|
||||
# From here down, almost the same as original (hanoi.bash) script.
|
||||
|
||||
dohanoi() { # Recursive function.
|
||||
case $1 in
|
||||
0)
|
||||
;;
|
||||
*)
|
||||
dohanoi "$(($1-1))" $2 $4 $3
|
||||
if [ "$Moves" -ne 0 ]
|
||||
then
|
||||
echo "+ Position after move $Moves"
|
||||
fi
|
||||
((Moves++))
|
||||
echo -n " Next move will be: "
|
||||
echo $2 "-->" $3
|
||||
display $2 $3
|
||||
dohanoi "$(($1-1))" $4 $3 $2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
setup_arrays ()
|
||||
{
|
||||
local dim n elem
|
||||
|
||||
let "dim1 = $1 - 1"
|
||||
elem=$dim1
|
||||
|
||||
for n in $(seq 0 $dim1)
|
||||
do
|
||||
let "Rod1[$elem] = 2 * $n + 1"
|
||||
Rod2[$n]=0
|
||||
Rod3[$n]=0
|
||||
((elem--))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
### Main ###
|
||||
|
||||
setup_arrays $DISKS
|
||||
echo; echo "+ Start Position"
|
||||
|
||||
case $# in
|
||||
1) case $(($1>0)) in # Must have at least one disk.
|
||||
1)
|
||||
disks=$1
|
||||
dohanoi $1 1 3 2
|
||||
# Total moves = 2^n - 1, where n = # of disks.
|
||||
echo
|
||||
exit 0;
|
||||
;;
|
||||
*)
|
||||
echo "$0: Illegal value for number of disks";
|
||||
exit $E_BADPARAM;
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 N"
|
||||
echo " Where \"N\" is the number of disks."
|
||||
exit $E_NOPARAM;
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $E_NOEXIT # Shouldn't exit here.
|
||||
|
||||
# Note:
|
||||
# Redirect script output to a file, otherwise it scrolls off display.
|
|
@ -0,0 +1,216 @@
|
|||
#! /bin/bash
|
||||
# The Towers Of Hanoi
|
||||
# Original script (hanoi.bash) copyright (C) 2000 Amit Singh.
|
||||
# All Rights Reserved.
|
||||
# http://hanoi.kernelthread.com
|
||||
|
||||
# hanoi2.bash
|
||||
# Version 2: modded for ASCII-graphic display.
|
||||
# Uses code contributed by Antonio Macchi,
|
||||
#+ with heavy editing by ABS Guide author.
|
||||
# This variant also falls under the original copyright, see above.
|
||||
# Used in ABS Guide with Amit Singh's permission (thanks!).
|
||||
|
||||
|
||||
# Variables #
|
||||
E_NOPARAM=86
|
||||
E_BADPARAM=87 # Illegal no. of disks passed to script.
|
||||
E_NOEXIT=88
|
||||
DELAY=2 # Interval, in seconds, between moves. Change, if desired.
|
||||
DISKS=$1
|
||||
Moves=0
|
||||
|
||||
MWIDTH=7
|
||||
MARGIN=2
|
||||
# Arbitrary "magic" constants, work okay for relatively small # of disks.
|
||||
# BASEWIDTH=51 # Original code.
|
||||
let "basewidth = $MWIDTH * $DISKS + $MARGIN" # "Base" beneath rods.
|
||||
# Above "algorithm" could likely stand improvement.
|
||||
|
||||
# Display variables.
|
||||
let "disks1 = $DISKS - 1"
|
||||
let "spaces1 = $DISKS"
|
||||
let "spaces2 = 2 * $DISKS"
|
||||
|
||||
let "lastmove_t = $DISKS - 1" # Final move?
|
||||
|
||||
|
||||
declare -a Rod1 Rod2 Rod3
|
||||
|
||||
#################
|
||||
|
||||
|
||||
function repeat { # $1=char $2=number of repetitions
|
||||
local n # Repeat-print a character.
|
||||
|
||||
for (( n=0; n<$2; n++ )); do
|
||||
echo -n "$1"
|
||||
done
|
||||
}
|
||||
|
||||
function FromRod {
|
||||
local rod summit weight sequence
|
||||
|
||||
while true; do
|
||||
rod=$1
|
||||
test ${rod/[^123]/} || continue
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for summit in $sequence; do
|
||||
eval weight=\${Rod${rod}[$summit]}
|
||||
test $weight -ne 0 &&
|
||||
{ echo "$rod $summit $weight"; return; }
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function ToRod { # $1=previous (FromRod) weight
|
||||
local rod firstfree weight sequence
|
||||
|
||||
while true; do
|
||||
rod=$2
|
||||
test ${rod/[^123]} || continue
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for firstfree in $sequence; do
|
||||
eval weight=\${Rod${rod}[$firstfree]}
|
||||
test $weight -gt 0 && { (( firstfree++ )); break; }
|
||||
done
|
||||
test $weight -gt $1 -o $firstfree = 0 &&
|
||||
{ echo "$rod $firstfree"; return; }
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function PrintRods {
|
||||
local disk rod empty fill sp sequence
|
||||
|
||||
tput cup 5 0
|
||||
|
||||
repeat " " $spaces1
|
||||
echo -n "|"
|
||||
repeat " " $spaces2
|
||||
echo -n "|"
|
||||
repeat " " $spaces2
|
||||
echo "|"
|
||||
|
||||
sequence=$(echo $(seq 0 $disks1 | tac))
|
||||
for disk in $sequence; do
|
||||
for rod in {1..3}; do
|
||||
eval empty=$(( $DISKS - (Rod${rod}[$disk] / 2) ))
|
||||
eval fill=\${Rod${rod}[$disk]}
|
||||
repeat " " $empty
|
||||
test $fill -gt 0 && repeat "*" $fill || echo -n "|"
|
||||
repeat " " $empty
|
||||
done
|
||||
echo
|
||||
done
|
||||
repeat "=" $basewidth # Print "base" beneath rods.
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
display ()
|
||||
{
|
||||
echo
|
||||
PrintRods
|
||||
|
||||
# Get rod-number, summit and weight
|
||||
first=( `FromRod $1` )
|
||||
eval Rod${first[0]}[${first[1]}]=0
|
||||
|
||||
# Get rod-number and first-free position
|
||||
second=( `ToRod ${first[2]} $2` )
|
||||
eval Rod${second[0]}[${second[1]}]=${first[2]}
|
||||
|
||||
|
||||
if [ "${Rod3[lastmove_t]}" = 1 ]
|
||||
then # Last move? If yes, then display final position.
|
||||
tput cup 0 0
|
||||
echo; echo "+ Final Position: $Moves moves"
|
||||
PrintRods
|
||||
fi
|
||||
|
||||
sleep $DELAY
|
||||
}
|
||||
|
||||
# From here down, almost the same as original (hanoi.bash) script.
|
||||
|
||||
dohanoi() { # Recursive function.
|
||||
case $1 in
|
||||
0)
|
||||
;;
|
||||
*)
|
||||
dohanoi "$(($1-1))" $2 $4 $3
|
||||
if [ "$Moves" -ne 0 ]
|
||||
then
|
||||
tput cup 0 0
|
||||
echo; echo "+ Position after move $Moves"
|
||||
fi
|
||||
((Moves++))
|
||||
echo -n " Next move will be: "
|
||||
echo $2 "-->" $3
|
||||
display $2 $3
|
||||
dohanoi "$(($1-1))" $4 $3 $2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
setup_arrays ()
|
||||
{
|
||||
local dim n elem
|
||||
|
||||
let "dim1 = $1 - 1"
|
||||
elem=$dim1
|
||||
|
||||
for n in $(seq 0 $dim1)
|
||||
do
|
||||
let "Rod1[$elem] = 2 * $n + 1"
|
||||
Rod2[$n]=0
|
||||
Rod3[$n]=0
|
||||
((elem--))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
### Main ###
|
||||
|
||||
trap "tput cnorm" 0
|
||||
tput civis
|
||||
clear
|
||||
|
||||
setup_arrays $DISKS
|
||||
|
||||
tput cup 0 0
|
||||
echo; echo "+ Start Position"
|
||||
|
||||
case $# in
|
||||
1) case $(($1>0)) in # Must have at least one disk.
|
||||
1)
|
||||
disks=$1
|
||||
dohanoi $1 1 3 2
|
||||
# Total moves = 2^n - 1, where n = # of disks.
|
||||
echo
|
||||
exit 0;
|
||||
;;
|
||||
*)
|
||||
echo "$0: Illegal value for number of disks";
|
||||
exit $E_BADPARAM;
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 N"
|
||||
echo " Where \"N\" is the number of disks."
|
||||
exit $E_NOPARAM;
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $E_NOEXIT # Shouldn't exit here.
|
||||
|
||||
# Exercise:
|
||||
# --------
|
||||
# There is a minor bug in the script that causes the display of
|
||||
#+ the next-to-last move to be skipped.
|
||||
#+ Fix this.
|
|
@ -10,8 +10,10 @@ 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.
|
||||
# Not useful ...
|
||||
# \$\$ expanded to PID of process being executed,
|
||||
#+ and "var" is echoed as plain text.
|
||||
# (Thank you, Jakob Bohm, for pointing this out.)
|
||||
|
||||
echo "\\\$\$var = \$$var" # \$$var = $23
|
||||
# As expected. The first $ is escaped and pasted on to
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#!/bin/bash
|
||||
# wr-ps.bash: while-read loop with process substitution.
|
||||
|
||||
# This example contributed by Tomas Pospisek.
|
||||
# (Heavily edited by the ABS Guide author.)
|
||||
|
||||
echo
|
||||
|
||||
echo "random input" | while read i
|
||||
do
|
||||
global=3D": Not available outside the loop."
|
||||
# ... because it runs in a subshell.
|
||||
done
|
||||
|
||||
echo "\$global (from outside the subprocess) = $global"
|
||||
# $global (from outside the subprocess) =
|
||||
|
||||
echo; echo "--"; echo
|
||||
|
||||
while read i
|
||||
do
|
||||
echo $i
|
||||
global=3D": Available outside the loop."
|
||||
# ... because it does *not* run in a subshell.
|
||||
done < <( echo "random input" )
|
||||
# ^ ^
|
||||
|
||||
echo "\$global (using process substitution) = $global"
|
||||
# random input
|
||||
# $global (using process substitution) = 3D: Available outside the loop.
|
||||
|
||||
|
||||
echo; echo "##########"; echo
|
||||
|
||||
|
||||
|
||||
# And likewise . . .
|
||||
|
||||
declare -a inloop
|
||||
index=0
|
||||
cat $0 | while read line
|
||||
do
|
||||
inloop[$index]="$line"
|
||||
((index++))
|
||||
# It runs in a subshell, so ...
|
||||
done
|
||||
echo "OUTPUT = "
|
||||
echo ${inloop[*]} # ... nothing echoes.
|
||||
|
||||
|
||||
echo; echo "--"; echo
|
||||
|
||||
|
||||
declare -a outloop
|
||||
index=0
|
||||
while read line
|
||||
do
|
||||
outloop[$index]="$line"
|
||||
((index++))
|
||||
# It does *not* run in a subshell, so ...
|
||||
done < <( cat $0 )
|
||||
echo "OUTPUT = "
|
||||
echo ${outloop[*]} # ... the entire script echoes.
|
||||
|
||||
exit $?
|
Loading…
Reference in New Issue