mirror of https://github.com/tLDP/LDP
updated
This commit is contained in:
parent
8456bfd681
commit
8b4da601ad
|
@ -7,17 +7,89 @@
|
|||
|
||||
|
||||
==================================================================
|
||||
Current version = 5.2
|
||||
http://personal.riverusers.com/~thegrendel/abs-guide-5.2.tar.bz2
|
||||
Current version = 5.3
|
||||
http://personal.riverusers.com/~thegrendel/abs-guide-5.3.tar.bz2
|
||||
http://personal.riverusers.com/~thegrendel/abs-guide.pdf
|
||||
|
||||
------------------------------------------------------------------
|
||||
News: Version 5.2 release. . . .
|
||||
New example scripts.
|
||||
New section on version 3.2 update to Bash.
|
||||
More on !#/bin/env bash.
|
||||
More coherent definition of "recursion."
|
||||
==================================================================
|
||||
--------------------------------------------------------------------
|
||||
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.
|
||||
====================================================================
|
||||
|
||||
Version 5.3, Goldenberry release
|
||||
05/11/08
|
||||
|
||||
1) In "Special Variable Types" section of "Introduction to Variables and
|
||||
Fixed exit-status error in second "shift-past.sh" example.
|
||||
(Thank you, E. Choroba!)
|
||||
At "#" entry, added "quoted" to "escaped" for "#" in non-comment lines.
|
||||
Added a number of missing "Ctl-?" entries. Now, the entire alphabet
|
||||
is complete <g>.
|
||||
At "Ctl-N" entry, added footnote about history buffer.
|
||||
|
||||
2) In "Tests" chapter:
|
||||
In "Test Constructs" section:
|
||||
At [[ double brackets ]] construct, added discussion and example on
|
||||
arithmetic evaluation of octal and hex constants within [[ ... ]].
|
||||
(Thank you, Moritz Gronbach!)
|
||||
Consolidated entire [[ ... ]] topic into a single <sidebar>.
|
||||
|
||||
3) In "Text Processing" section of "External Commands" Chapter:
|
||||
Added "cw-solver.sh" (crossword puzzle solver) example script.
|
||||
|
||||
4) In "System and Administrative Commands" chapter:
|
||||
At "lockfile" entry:
|
||||
Updated in-line example per suggestion of E. Choroba.
|
||||
Added info to footnote defining "semaphore."
|
||||
|
||||
5) In "Internal Commands and Builtins" chapter:
|
||||
At "read" entry, appended Antonio Macchi's suggestions to
|
||||
"arrow-detect.sh" example.
|
||||
|
||||
6) In "Quoting Variables" section of "Quoting" chapter:
|
||||
Added simple in-line example.
|
||||
|
||||
7) In "Debugging" chapter:
|
||||
Changed note defining 'signal' into a sidebar and removed superfluous
|
||||
comma.
|
||||
|
||||
8) In "Gotchas" chapter:
|
||||
Added item about unintended consequences of preserving whitespace
|
||||
within a variable. (Thank you, Claus Tirel, for inspiring me to do
|
||||
this.)
|
||||
|
||||
9) In "Assorted Tips" section of "Miscellany" chapter:
|
||||
At return value trickery discussion,
|
||||
added Caution about only one "echo" statement in a function.
|
||||
|
||||
10) In "Operator Precedence" section "Miscellany" chapter:
|
||||
Fixed an error in the table (!= is not a "combination assignment"
|
||||
operator.
|
||||
|
||||
11) In "Contributed Scripts" appendix:
|
||||
Added "Petals Around the Rose" example script.
|
||||
(Thank you, Serghey Rodin!)
|
||||
Modified "basics-reviewed.bash" script, per contribution
|
||||
of Cliff Bamford. (Many thanks!)
|
||||
In "basics-reviewed.bash" script, fixed two typos.
|
||||
Added very long and complex "qky.sh" (Perquackey-type game) script.
|
||||
|
||||
12) In "Exit Codes With Special Meanings" appendix:
|
||||
Added footnote about previously unused exit codes
|
||||
in the 64-78 range now allocated.
|
||||
(Thank you, Greg Metcalfe, for pointing this out.)
|
||||
|
||||
13) In "Bibliography" section:
|
||||
Added reference/link to Penguin Pete's site.
|
||||
|
||||
14) In "Exercise" appendix:
|
||||
Added humorous preface.
|
||||
|
||||
15) Cleanups/fixups to main text, appendices, and script examples where
|
||||
appropriate.
|
||||
|
||||
|
||||
|
||||
Version 5.2, Silverberry release
|
||||
03/16/08
|
||||
|
|
|
@ -698,6 +698,8 @@
|
|||
<firstterm>unalias</firstterm></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="agram2">Anagramming</link></para>
|
||||
|
||||
<para><link linkend="lcons1"><firstterm>And</firstterm> list</link>
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
|
@ -809,6 +811,8 @@
|
|||
elements</link></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><link linkend="readarrow">Arrow keys</link>, detecting</para>
|
||||
|
||||
<para><link linkend="asciitable">ASCII table</link></para>
|
||||
|
||||
<!-- ********************** -->
|
||||
|
@ -880,6 +884,8 @@
|
|||
<para><link linkend="biblio">Bibliography</link></para>
|
||||
<para><link linkend="bisonref">Bison</link> utility</para>
|
||||
<para><link linkend="bitwsops1">Bitwise operators</link></para>
|
||||
<para><link linkend="blockdevref">Block devices</link>, testing
|
||||
for</para>
|
||||
|
||||
<para><link linkend="codeblockref">Blocks of code</link>
|
||||
<itemizedlist>
|
||||
|
@ -969,6 +975,8 @@
|
|||
</itemizedlist></para>
|
||||
|
||||
|
||||
<para><link linkend="chardevref">Character devices</link>, testing
|
||||
for</para>
|
||||
<para><link linkend="childref">Child processes</link></para>
|
||||
<para><link linkend="nullref">Colon</link>, <command>: </command>,
|
||||
equivalent to the <link linkend="trueref">true</link> Bash
|
||||
|
@ -1063,6 +1071,8 @@
|
|||
<para><link linkend="cstyle"><firstterm>C</firstterm>-style syntax
|
||||
</link>, for handling variables</para>
|
||||
|
||||
<para><link linkend="cwsolver">Crossword puzzle solver</link></para>
|
||||
|
||||
<para>Curly brackets {}
|
||||
<itemizedlist>
|
||||
<listitem><para><link linkend="curlybracketsref">in
|
||||
|
@ -1169,9 +1179,15 @@
|
|||
(<command>table</command>)</para>
|
||||
<para><link linkend="dotfilesref"><firstterm>dot files</firstterm></link>,
|
||||
<quote>hidden</quote> setup and configuration files</para>
|
||||
|
||||
<para><link linkend="dblbrackets">Double brackets</link>
|
||||
<command>[[ ... ]]</command> <link linkend="ifthen">test</link>
|
||||
construct</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>and <link linkend="dblbraev">evaluation of
|
||||
<firstterm>octal/hex</firstterm> constants</link></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><link linkend="dblquo">Double quotes</link>
|
||||
<command>" ... "</command> <firstterm>weak</firstterm> quoting</para>
|
||||
<para><link linkend="doublespace">Double-spacing a text
|
||||
|
@ -1223,6 +1239,10 @@
|
|||
using</link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="dblbraev">Evaluation of
|
||||
<firstterm>octal/hex</firstterm> constants within
|
||||
[[ ... ]]</link></para>
|
||||
|
||||
<para><link linkend="usingexecref">exec</link> command,
|
||||
using in <link linkend="ioredirref">redirection</link></para>
|
||||
|
||||
|
@ -1548,6 +1568,8 @@
|
|||
loop</para>
|
||||
<para><link linkend="inittabref">Initialization table</link>,
|
||||
<filename>/etc/inittab</filename></para>
|
||||
<para><link linkend="codeblockref">Inline group</link>,
|
||||
i.e., code block</para>
|
||||
<para><link linkend="iitest">Interactive script</link>, test for</para>
|
||||
<para><link linkend="ioredirref">I/O redirection</link></para>
|
||||
|
||||
|
@ -1897,6 +1919,12 @@
|
|||
with</link></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para><link linkend="qky"><emphasis>Perquackey</emphasis>-type
|
||||
anagramming game</link> (<emphasis>Quackey</emphasis> script)</para>
|
||||
|
||||
<para><link linkend="petals"><emphasis>Petals Around the
|
||||
Rose</emphasis></link></para>
|
||||
|
||||
<para><link linkend="processiddef">PID</link>,
|
||||
<firstterm>Process ID</firstterm>, an identification
|
||||
number assigned to a running process.</para>
|
||||
|
@ -1965,6 +1993,9 @@
|
|||
within <firstterm>test</firstterm> brackets</para></listitem>
|
||||
<listitem><para><link linkend="gnuref"><firstterm>GNU</firstterm>
|
||||
command set</link>, in cross-platform scripts</para></listitem>
|
||||
<listitem><para><link linkend="rvtcaution2">Multiple echo
|
||||
statements</link> in a <link linkend="rvt">function whose
|
||||
output is captured</link></para></listitem>
|
||||
<listitem><para><link linkend="nullvar"><firstterm>null</firstterm>
|
||||
variable assignment</link></para></listitem>
|
||||
<listitem>
|
||||
|
@ -1988,6 +2019,9 @@
|
|||
<para><link linkend="ptailgrep"><firstterm>tail</firstterm>
|
||||
<option>-f</option> to <firstterm>grep</firstterm></link></para>
|
||||
</listitem>
|
||||
<listitem><para>Preserving <firstterm>whitespace</firstterm>
|
||||
within a variable, <link linkend="varsplitting">unintended
|
||||
consequences</link></para></listitem>
|
||||
<listitem><para><link linkend="suidscr"><firstterm>suid</firstterm>
|
||||
commands inside a script</link></para></listitem>
|
||||
<listitem><para><link linkend="undocf">Undocumented
|
||||
|
@ -2125,6 +2159,9 @@
|
|||
|
||||
<para>* * *</para>
|
||||
|
||||
<para><link linkend="qky">Quackey</link>, a
|
||||
<emphasis>Perquackey</emphasis>-type anagramming game (script)</para>
|
||||
|
||||
<para>Question mark, <command>? </command>
|
||||
<itemizedlist>
|
||||
<listitem><para><link linkend="quexregex">Character
|
||||
|
@ -2552,6 +2589,16 @@
|
|||
<firstterm>script example</firstterm></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><firstterm>strchr()</firstterm>, <link
|
||||
linkend="substringindex2">equivalent of</link></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><firstterm>strlen()</firstterm>, <link
|
||||
linkend="strlen">equivalent of</link></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Substring extraction</para>
|
||||
<para><link linkend="substrextr01">${string:position}</link></para>
|
||||
|
@ -2789,6 +2836,10 @@
|
|||
<firstterm>return value</firstterm> from
|
||||
a function</link></para></listitem>
|
||||
|
||||
<listitem><para><link linkend="captureretval">Capturing
|
||||
the return value</link> of a function, using
|
||||
<firstterm>echo</firstterm></para></listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Comment blocks</para>
|
||||
<para>Using <link linkend="cblock1"><firstterm>anonymous
|
||||
|
@ -2980,7 +3031,7 @@
|
|||
<para><link
|
||||
linkend="failquote">within <firstterm>test</firstterm>
|
||||
brackets</link></para>
|
||||
<para><link linkend="quotingws">to preserve
|
||||
<para><link linkend="wsquo">to preserve
|
||||
<firstterm>whitespace</firstterm></link></para>
|
||||
</listitem>
|
||||
<listitem><para><link
|
||||
|
@ -2999,10 +3050,13 @@
|
|||
error message</para></listitem>
|
||||
<listitem><para><link linkend="uninitvar1">Uninitialized</link>
|
||||
</para></listitem>
|
||||
<listitem><para><link linkend="varsplitting">Unquoted
|
||||
variable</link>,
|
||||
<firstterm>splitting</firstterm></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="unsetref">Unsetting</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="unsetref">Unsetting</link></para></listitem>
|
||||
<listitem><para><link
|
||||
linkend="bvuntyped">Untyped</link></para></listitem>
|
||||
linkend="bvuntyped">Untyped</link></para></listitem>
|
||||
|
||||
</itemizedlist></para>
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ hash-example.sh (comment in line 3: < --> <, > --> >)
|
|||
quote-fetch.sh (comment in line 26: & --> &)
|
||||
ftpget.sh (comment in line 28)
|
||||
whx.sh (comment in line 259)
|
||||
pad.sh, (comment in line 6, lines 26, 27, 28, 29, 30, 33, 34).
|
||||
pad.sh, (comments in line 6, lines 26, 27, 28, 29, 30, 33, 34).
|
||||
nightly-backup.sh (comment in line 4)
|
||||
tohtml.sh: lines 22-33
|
||||
lines 35-36
|
||||
|
@ -91,3 +91,14 @@ insertion-sort.sh:
|
|||
tree2.sh:
|
||||
line 38 (comment)
|
||||
line 88
|
||||
|
||||
petals.sh
|
||||
line 54
|
||||
|
||||
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)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -96,6 +96,29 @@ exit $OTHER
|
|||
;;
|
||||
esac
|
||||
|
||||
exit $?
|
||||
|
||||
# ========================================= #
|
||||
|
||||
# Antonio Macchi has a simpler alternative.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
while true
|
||||
do
|
||||
read -sn1 a
|
||||
test "$a" == `echo -en "\e"` || continue
|
||||
read -sn1 a
|
||||
test "$a" == "[" || continue
|
||||
read -sn1 a
|
||||
case "$a" in
|
||||
A) echo "up";;
|
||||
B) echo "down";;
|
||||
C) echo "right";;
|
||||
D) echo "left";;
|
||||
esac
|
||||
done
|
||||
|
||||
# ========================================= #
|
||||
|
||||
# Exercise:
|
||||
|
|
|
@ -9,15 +9,16 @@
|
|||
#
|
||||
# Edited for layout by M.C.
|
||||
# (author of the "Advanced Bash Scripting Guide")
|
||||
# Fixes and updates (04/08) by Cliff Bamford.
|
||||
|
||||
|
||||
# This script tested under Bash versions 2.04, 2.05a and 2.05b.
|
||||
# It may not work with earlier versions.
|
||||
# This demonstration script generates one --intentional--
|
||||
#+ "command not found" error message. See line 394.
|
||||
#+ "command not found" error message. See line 436.
|
||||
|
||||
# The current Bash maintainer, Chet Ramey, has fixed the items noted
|
||||
#+ for an upcoming version of Bash.
|
||||
#+ for later versions of Bash.
|
||||
|
||||
|
||||
|
||||
|
@ -51,7 +52,7 @@ unset VarNull
|
|||
# A variable name may be defined but empty (null contents).
|
||||
VarEmpty='' # Two, adjacent, single quotes.
|
||||
|
||||
# A variable name my be defined and non-empty
|
||||
# A variable name may be defined and non-empty.
|
||||
VarSomething='Literal'
|
||||
|
||||
# A variable may contain:
|
||||
|
@ -174,7 +175,7 @@ echo ${@} # Same as above
|
|||
# Elements of a Bash-Array need not all be of the same type.
|
||||
###
|
||||
# Elements of a Bash-Array may be undefined (null reference).
|
||||
# That is, a Bash-Array my be "subscript sparse."
|
||||
# That is, a Bash-Array may be "subscript sparse."
|
||||
###
|
||||
# Elements of a Bash-Array may be defined and empty (null contents).
|
||||
###
|
||||
|
@ -196,102 +197,143 @@ echo ${@} # Same as above
|
|||
# -- msz
|
||||
|
||||
|
||||
echo "========================================================="
|
||||
|
||||
# Lines 202 - 334 supplied by Cliff Bamford. (Thanks!)
|
||||
# Demo --- Interaction with Arrays, quoting, IFS, echo, * and @ ---
|
||||
#+ all affect how things work
|
||||
|
||||
ArrayVar[0]='zero' # 0 normal
|
||||
ArrayVar[1]=one # 1 unquoted literal
|
||||
ArrayVar[2]='two' # 2 normal
|
||||
ArrayVar[3]='three' # 3 normal
|
||||
ArrayVar[4]='I am four' # 4 normal with spaces
|
||||
ArrayVar[5]='five' # 5 normal
|
||||
unset ArrayVar[6] # 6 undefined
|
||||
ArrayValue[7]='seven' # 7 normal
|
||||
ArrayValue[8]='' # 8 defined but empty
|
||||
ArrayValue[9]='nine' # 9 normal
|
||||
|
||||
|
||||
# Demo time -- initialize the previously declared ArrayVar as a
|
||||
#+ sparse array.
|
||||
# (The 'unset ... ' is just documentation here.)
|
||||
|
||||
unset ArrayVar[0] # Just for the record
|
||||
ArrayVar[1]=one # Unquoted literal
|
||||
ArrayVar[2]='' # Defined, and empty
|
||||
unset ArrayVar[3] # Just for the record
|
||||
ArrayVar[4]='four' # Quoted literal
|
||||
|
||||
|
||||
|
||||
# Translate the %q format as: Quoted-Respecting-IFS-Rules.
|
||||
echo '--- Here is the array we are using for this test'
|
||||
echo
|
||||
echo '- - Outside of double-quotes - -'
|
||||
###
|
||||
printf %q ${ArrayVar[*]} # Glob-Pattern All-Elements-Of
|
||||
echo "ArrayVar[0]='zero' # 0 normal"
|
||||
echo "ArrayVar[1]=one # 1 unquoted literal"
|
||||
echo "ArrayVar[2]='two' # 2 normal"
|
||||
echo "ArrayVar[3]='three' # 3 normal"
|
||||
echo "ArrayVar[4]='I am four' # 4 normal with spaces"
|
||||
echo "ArrayVar[5]='five' # 5 normal"
|
||||
echo "unset ArrayVar[6] # 6 undefined"
|
||||
echo "ArrayValue[7]='seven' # 7 normal"
|
||||
echo "ArrayValue[8]='' # 8 defined but empty"
|
||||
echo "ArrayValue[9]='nine' # 9 normal"
|
||||
echo
|
||||
echo 'echo command:'${ArrayVar[*]}
|
||||
###
|
||||
printf %q ${ArrayVar[@]} # All-Elements-Of
|
||||
echo
|
||||
echo 'echo command:'${ArrayVar[@]}
|
||||
|
||||
# The use of double-quotes may be translated as: Enable-Substitution.
|
||||
|
||||
# There are five cases recognized for the IFS setting.
|
||||
|
||||
echo
|
||||
echo '- - Within double-quotes - Default IFS of space-tab-newline - -'
|
||||
IFS=$'\x20'$'\x09'$'\x0A' # These three bytes,
|
||||
#+ in exactly this order.
|
||||
|
||||
|
||||
printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Of
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[*]}"
|
||||
###
|
||||
printf %q "${ArrayVar[@]}" # All-Elements-Of
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[@]}"
|
||||
|
||||
|
||||
echo
|
||||
echo '- - Within double-quotes - First character of IFS is ^ - -'
|
||||
# Any printing, non-whitespace character should do the same.
|
||||
IFS='^'$IFS # ^ + space tab newline
|
||||
###
|
||||
printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Of
|
||||
echo '---Case0: No double-quotes, Default IFS of space,tab,newline ---'
|
||||
IFS=$'\x20'$'\x09'$'\x0A' # In exactly this order.
|
||||
echo 'Here is: printf %q {${ArrayVar[*]}'
|
||||
printf %q ${ArrayVar[*]}
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[*]}"
|
||||
###
|
||||
printf %q "${ArrayVar[@]}" # All-Elements-Of
|
||||
echo 'Here is: printf %q {${ArrayVar[@]}'
|
||||
printf %q ${ArrayVar[@]}
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[@]}"
|
||||
|
||||
echo 'Here is: echo ${ArrayVar[*]}'
|
||||
echo ${ArrayVar[@]}
|
||||
echo 'Here is: echo {${ArrayVar[@]}'
|
||||
echo ${ArrayVar[@]}
|
||||
|
||||
echo
|
||||
echo '- - Within double-quotes - Without whitespace in IFS - -'
|
||||
IFS='^:%!'
|
||||
###
|
||||
printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Of
|
||||
echo '---Case1: Within double-quotes - Default IFS of space-tab-
|
||||
newline ---'
|
||||
IFS=$'\x20'$'\x09'$'\x0A' # These three bytes,
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[*]}"
|
||||
###
|
||||
printf %q "${ArrayVar[@]}" # All-Elements-Of
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[@]}"
|
||||
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '- - Within double-quotes - IFS set and empty - -'
|
||||
echo '---Case2: Within double-quotes - IFS is q'
|
||||
IFS='q'
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '---Case3: Within double-quotes - IFS is ^'
|
||||
IFS='^'
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '---Case4: Within double-quotes - IFS is ^ followed by
|
||||
space,tab,newline'
|
||||
IFS=$'^'$'\x20'$'\x09'$'\x0A' # ^ + space tab newline
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '---Case6: Within double-quotes - IFS set and empty '
|
||||
IFS=''
|
||||
###
|
||||
printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Of
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[*]}"
|
||||
###
|
||||
printf %q "${ArrayVar[@]}" # All-Elements-Of
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[@]}"
|
||||
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '- - Within double-quotes - IFS undefined - -'
|
||||
echo '---Case7: Within double-quotes - IFS is unset'
|
||||
unset IFS
|
||||
###
|
||||
printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Of
|
||||
echo 'Here is: printf %q "{${ArrayVar[*]}"'
|
||||
printf %q "${ArrayVar[*]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[*]}"
|
||||
###
|
||||
printf %q "${ArrayVar[@]}" # All-Elements-Of
|
||||
echo 'Here is: printf %q "{${ArrayVar[@]}"'
|
||||
printf %q "${ArrayVar[@]}"
|
||||
echo
|
||||
echo 'echo command:'"${ArrayVar[@]}"
|
||||
echo 'Here is: echo "${ArrayVar[*]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
echo 'Here is: echo "{${ArrayVar[@]}"'
|
||||
echo "${ArrayVar[@]}"
|
||||
|
||||
echo
|
||||
echo '---End of Cases---'
|
||||
echo "========================================================="; echo
|
||||
|
||||
|
||||
|
||||
# Put IFS back to the default.
|
||||
|
@ -392,7 +434,7 @@ echo $_simple not defined # No variable by that name.
|
|||
|
||||
###
|
||||
$(_simple) # Gives an error message:
|
||||
# line 394: SimpleFunc: command not found
|
||||
# line 436: SimpleFunc: command not found
|
||||
# ---------------------------------------
|
||||
|
||||
echo
|
||||
|
@ -784,8 +826,7 @@ echo ${ArrayVar[@]:1:2} # four - The only element with content.
|
|||
# In versions 2.04, 2.05a and 2.05b,
|
||||
#+ Bash does not handle sparse arrays as expected using this notation.
|
||||
#
|
||||
# The current Bash maintainer, Chet Ramey, has corrected this
|
||||
#+ for an upcoming version of Bash.
|
||||
# The current Bash maintainer, Chet Ramey, has corrected this.
|
||||
|
||||
|
||||
echo '- Non-sparse array -'
|
||||
|
@ -821,8 +862,8 @@ echo ${stringZ#123} # Unchanged (not a prefix).
|
|||
echo ${stringZ#$(_abc)} # ABC123ABCabc
|
||||
echo ${arrayZ[@]#abc} # Applied to each element.
|
||||
|
||||
# Fixed by Chet Ramey for an upcoming version of Bash.
|
||||
# echo ${sparseZ[@]#abc} # Version-2.05b core dumps.
|
||||
# Has since been fixed by Chet Ramey.
|
||||
|
||||
# The -it would be nice- First-Subscript-Of
|
||||
# echo ${#sparseZ[@]#*} # This is NOT valid Bash.
|
||||
|
@ -833,8 +874,8 @@ echo ${stringZ##1*3} # Unchanged (not a prefix)
|
|||
echo ${stringZ##a*C} # abc
|
||||
echo ${arrayZ[@]##a*c} # ABCABC 123123 ABCABC
|
||||
|
||||
# Fixed by Chet Ramey for an upcoming version of Bash
|
||||
# echo ${sparseZ[@]##a*c} # Version-2.05b core dumps.
|
||||
# Has since been fixed by Chet Ramey.
|
||||
|
||||
echo
|
||||
echo '- - Suffix sub-element removal - -'
|
||||
|
@ -846,8 +887,8 @@ echo ${stringZ%1*3} # Unchanged (not a suffix).
|
|||
echo ${stringZ%$(_abc)} # abcABC123ABC
|
||||
echo ${arrayZ[@]%abc} # Applied to each element.
|
||||
|
||||
# Fixed by Chet Ramey for an upcoming version of Bash.
|
||||
# echo ${sparseZ[@]%abc} # Version-2.05b core dumps.
|
||||
# Has since been fixed by Chet Ramey.
|
||||
|
||||
# The -it would be nice- Last-Subscript-Of
|
||||
# echo ${#sparseZ[@]%*} # This is NOT valid Bash.
|
||||
|
@ -858,8 +899,8 @@ echo ${stringZ%%1*3} # Unchanged (not a suffix)
|
|||
echo ${stringZ%%b*c} # a
|
||||
echo ${arrayZ[@]%%b*c} # a ABCABC 123123 ABCABC a
|
||||
|
||||
# Fixed by Chet Ramey for an upcoming version of Bash.
|
||||
# echo ${sparseZ[@]%%b*c} # Version-2.05b core dumps.
|
||||
# Has since been fixed by Chet Ramey.
|
||||
|
||||
echo
|
||||
echo '- - Sub-element replacement - -'
|
||||
|
|
|
@ -23,19 +23,21 @@
|
|||
#+ disregards such parameters as
|
||||
#+ board tilt-angle, rolling friction of the marbles,
|
||||
#+ angles of impact, and elasticity of the pegs.
|
||||
# How does this affect the accuracy of the simulation?
|
||||
# To what extent does this affect the accuracy of the simulation?
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
PASSES=500 # Number of particle interactions / marbles.
|
||||
ROWS=10 # Number of "collisions" (or horiz. peg rows).
|
||||
RANGE=3 # 0 - 2 output range from $RANDOM.
|
||||
POS=0 # Left/right position.
|
||||
PASSES=500 # Number of particle interactions / marbles.
|
||||
ROWS=10 # Number of "collisions" (or horiz. peg rows).
|
||||
RANGE=3 # 0 - 2 output range from $RANDOM.
|
||||
POS=0 # Left/right position.
|
||||
RANDOM=$$ # Seeds the random number generator from PID
|
||||
#+ of script.
|
||||
|
||||
declare -a Slots # Array holding cumulative results of passes.
|
||||
NUMSLOTS=21 # Number of slots at bottom of board.
|
||||
|
||||
|
||||
Initialize_Slots () { # Zero out all elements of array.
|
||||
Initialize_Slots () { # Zero out all elements of the array.
|
||||
for i in $( seq $NUMSLOTS )
|
||||
do
|
||||
Slots[$i]=0
|
||||
|
@ -49,7 +51,7 @@ Show_Slots () {
|
|||
echo -n " "
|
||||
for i in $( seq $NUMSLOTS ) # Pretty-print array elements.
|
||||
do
|
||||
printf "%3d" ${Slots[$i]} # Three spaces per result.
|
||||
printf "%3d" ${Slots[$i]} # Allot three spaces per result.
|
||||
done
|
||||
|
||||
echo # Row of slots:
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
# Theoretically, the more shots taken, the better the fit.
|
||||
# However, a shell script, as opposed to a compiled language
|
||||
#+ with floating-point math built in, requires a few compromises.
|
||||
# This tends to lower the accuracy of the simulation, of course.
|
||||
# This tends to lower the accuracy of the simulation.
|
||||
|
||||
|
||||
DIMENSION=10000 # Length of each side of the plot.
|
||||
|
@ -42,6 +42,8 @@ MAXSHOTS=1000 # Fire this many shots.
|
|||
# 10000 or more would be better, but would take too long.
|
||||
PMULTIPLIER=4.0 # Scaling factor to approximate PI.
|
||||
|
||||
M_PI=3.141592654 # Actual value of PI, for comparison purposes.
|
||||
|
||||
get_random ()
|
||||
{
|
||||
SEED=$(head -n 1 /dev/urandom | od -N 1 | awk '{ print $2 }')
|
||||
|
@ -61,7 +63,7 @@ EOF
|
|||
)
|
||||
# Setting "scale" to zero rounds down result to integer value,
|
||||
#+ a necessary compromise in this script.
|
||||
# This diminshes the accuracy of the simulation, unfortunately.
|
||||
# This diminshes the accuracy of the simulation.
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,6 +74,7 @@ shots=0
|
|||
splashes=0
|
||||
thuds=0
|
||||
Pi=0
|
||||
error=0
|
||||
|
||||
while [ "$shots" -lt "$MAXSHOTS" ] # Main loop.
|
||||
do
|
||||
|
@ -107,9 +110,11 @@ do
|
|||
done
|
||||
|
||||
echo
|
||||
echo "After $shots shots, PI looks like approximately $Pi."
|
||||
echo "After $shots shots, PI looks like approximately $Pi"
|
||||
# Tends to run a bit high . . .
|
||||
# Probably due to round-off error and imperfect randomness of $RANDOM.
|
||||
error=$(echo "scale=9; $Pi - $M_PI" | bc)
|
||||
echo "Deviation from mathematical value of PI = $error"
|
||||
echo
|
||||
|
||||
# }
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/bash
|
||||
# cw-solver.sh
|
||||
|
||||
# Crossword puzzle and anagramming word game solver.
|
||||
# You know *some* of the letters in the word you're looking for,
|
||||
#+ so you need a list of all valid words
|
||||
#+ with the known letters in given positions.
|
||||
# For example: w...i....n
|
||||
# 1???5????10
|
||||
# w in position 1, 3 unknowns, i in the 5th, 4 unknowns, n at the end.
|
||||
# (See comments at end of script.)
|
||||
|
||||
|
||||
E_NOPATT=71
|
||||
DICT=/usr/share/dict/word.lst
|
||||
# ^^^^^^^^ Looks for word list here.
|
||||
# ASCII word list, one word per line.
|
||||
# If you happen to need an appropriate list,
|
||||
#+ download the author's "yawl" word list package.
|
||||
# http://ibiblio.org/pub/Linux/libs/yawl-0.3.2.tar.gz
|
||||
# or
|
||||
# http://personal.riverusers.com/~thegrendel/yawl-0.3.2.tar.gz
|
||||
|
||||
|
||||
if [ -z "$1" ] # If no word pattern specified
|
||||
then #+ as a command-line argument . . .
|
||||
echo #+ . . . then . . .
|
||||
echo "Usage:" #+ Usage message.
|
||||
echo
|
||||
echo ""$0" \"pattern,\""
|
||||
echo "where \"pattern\" is in the form"
|
||||
echo "xxx..x.x..."
|
||||
echo
|
||||
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
|
||||
exit $E_NOPATT
|
||||
fi
|
||||
|
||||
echo
|
||||
# ===============================================
|
||||
# This is where all the work gets done.
|
||||
grep ^"$1"$ "$DICT" # Yes, only one line!
|
||||
# | |
|
||||
# ^ is start-of-word regex anchor.
|
||||
# $ is end-of-word regex anchor.
|
||||
|
||||
# From _Stupid Grep Tricks_, vol. 1,
|
||||
#+ a book the ABS Guide author may yet get around
|
||||
#+ to writing one of these days . . .
|
||||
# ===============================================
|
||||
echo
|
||||
|
||||
|
||||
exit $? # Script terminates here.
|
||||
# If there are too many words generated,
|
||||
#+ redirect the output to a file.
|
||||
|
||||
cw-solver w...i....n
|
||||
|
||||
twichildren
|
||||
wellington
|
||||
workingman
|
||||
workingmen
|
|
@ -1,5 +1,8 @@
|
|||
#!/bin/bash
|
||||
# Creating a swapfile.
|
||||
# Creating a swap file.
|
||||
|
||||
# A swap file provides a temporary storage cache
|
||||
#+ which helps speed up certain filesystem operations.
|
||||
|
||||
ROOT_UID=0 # Root has $UID 0.
|
||||
E_WRONG_USER=65 # Not root?
|
||||
|
|
|
@ -10,23 +10,24 @@
|
|||
# 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". #
|
||||
#+ 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. #
|
||||
# #
|
||||
# 123 #
|
||||
# 4*5 #
|
||||
# 4*5 The * is the cell in question. #
|
||||
# 678 #
|
||||
# #
|
||||
# 2) A living cell with either 2 or 3 living neighbors remains alive. #
|
||||
# 3) A dead cell with 3 living neighbors becomes alive (a "birth"). #
|
||||
SURVIVE=2 #
|
||||
# 3) A dead cell with 3 living neighbors becomes alive (a "birth"). #
|
||||
BIRTH=3 #
|
||||
# 4) All other cases result in a dead cell for the next generation. #
|
||||
# ##################################################################### #
|
||||
|
||||
|
||||
startfile=gen0 # Read the starting generation from the file "gen0".
|
||||
startfile=gen0 # Read the starting generation from the file "gen0" ...
|
||||
# Default, if no other file specified when invoking script.
|
||||
#
|
||||
if [ -n "$1" ] # Specify another "generation 0" file.
|
||||
|
@ -36,7 +37,7 @@ fi
|
|||
|
||||
############################################
|
||||
# Abort script if "startfile" not specified
|
||||
#+ AND
|
||||
#+ and
|
||||
#+ "gen0" not present.
|
||||
|
||||
E_NOSTARTFILE=68
|
||||
|
@ -58,7 +59,7 @@ DEAD1=_
|
|||
#+ but a large grid will will cause very slow execution).
|
||||
ROWS=10
|
||||
COLS=10
|
||||
# Change above two variables to match grid size, if necessary.
|
||||
# Change above two variables to match grid size, as desired.
|
||||
# ---------------------------------------------------------- #
|
||||
|
||||
GENERATIONS=10 # How many generations to cycle through.
|
||||
|
@ -81,7 +82,7 @@ generation=0 # Initialize generation count.
|
|||
let "cells = $ROWS * $COLS"
|
||||
# How many cells.
|
||||
|
||||
declare -a initial # Arrays containing "cells".
|
||||
declare -a initial # Arrays containing "cells."
|
||||
declare -a current
|
||||
|
||||
display ()
|
||||
|
@ -229,8 +230,8 @@ GetCount () # Count live cells in passed cell's neighborhood.
|
|||
IsValid $t_top $row
|
||||
if [ $? -eq "$TRUE" ]
|
||||
then
|
||||
if [ ${array[$t_top]} = "$ALIVE1" ]
|
||||
then
|
||||
if [ ${array[$t_top]} = "$ALIVE1" ] # Redundancy here.
|
||||
then # Can be optimized?
|
||||
let "count += 1"
|
||||
fi
|
||||
fi
|
||||
|
@ -274,7 +275,7 @@ do
|
|||
array[$i]=. #+ represent the cell as a period.
|
||||
else
|
||||
array[$i]="_" # Otherwise underscore
|
||||
fi #+ (which will later be converted to space).
|
||||
fi #+ (will later be converted to space).
|
||||
let "i += 1"
|
||||
done
|
||||
|
||||
|
@ -368,3 +369,7 @@ exit 0 # END
|
|||
#+ for the script to run.
|
||||
# This would make unnecessary any changes to variables
|
||||
#+ in the script for an altered grid size.
|
||||
#
|
||||
# Exercise: Optimize this script.
|
||||
# It has some repetitive and redundant code,
|
||||
#+ for example, lines 335-336.
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<row>
|
||||
<entry><option>-e -f -t -x, etc.</option></entry>
|
||||
<entry><firstterm>unary</firstterm> comparison</entry>
|
||||
<entry><firstterm>files</firstterm></entry>
|
||||
<entry>file-test</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>< -lt > -gt <= -le >= -ge</option></entry>
|
||||
|
@ -90,10 +90,11 @@
|
|||
<row>
|
||||
<entry><option>-nt -ot -ef</option></entry>
|
||||
<entry><firstterm>compound</firstterm> comparison</entry>
|
||||
<entry><firstterm>files</firstterm></entry>
|
||||
<entry>file-test</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>== -eq != -ne</option></entry>
|
||||
<entry><option>== -eq <link linkend="notequal">!=</link>
|
||||
-ne</option></entry>
|
||||
<entry>equality / inequality</entry>
|
||||
<entry>test operators, string and integer</entry>
|
||||
</row>
|
||||
|
@ -152,7 +153,7 @@
|
|||
<firstterm>test</firstterm>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>*= /= %= += -= <<= >>= &= !=</option></entry>
|
||||
<entry><option>*= /= %= += -= <<= >>= &=</option></entry>
|
||||
<entry><link linkend="arithopscomb">combination
|
||||
assignment</link></entry>
|
||||
<entry>times-equal, divide-equal, mod-equal, etc.</entry>
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#!/bin/bash -i
|
||||
# petals.sh
|
||||
|
||||
#########################################################################
|
||||
# Petals Around the Rose #
|
||||
# #
|
||||
# Version 0.1 Created by Serghey Rodin #
|
||||
# Version 0.2 Modded by ABS Guide Author #
|
||||
# #
|
||||
# License: GPL3 #
|
||||
# Used in ABS Guide with permission. #
|
||||
# ##################################################################### #
|
||||
|
||||
hits=0 # Correct guesses.
|
||||
WIN=6 # Mastered the game.
|
||||
ALMOST=5 # One short of mastery.
|
||||
EXIT=exit # Give up early?
|
||||
|
||||
RANDOM=$$ # Seeds the random number generator from PID of script.
|
||||
|
||||
|
||||
# Bones (ASCII graphics for dice)
|
||||
bone1[1]="| |"
|
||||
bone1[2]="| o |"
|
||||
bone1[3]="| o |"
|
||||
bone1[4]="| o o |"
|
||||
bone1[5]="| o o |"
|
||||
bone1[6]="| o o |"
|
||||
bone2[1]="| o |"
|
||||
bone2[2]="| |"
|
||||
bone2[3]="| o |"
|
||||
bone2[4]="| |"
|
||||
bone2[5]="| o |"
|
||||
bone2[6]="| o o |"
|
||||
bone3[1]="| |"
|
||||
bone3[2]="| o |"
|
||||
bone3[3]="| o |"
|
||||
bone3[4]="| o o |"
|
||||
bone3[5]="| o o |"
|
||||
bone3[6]="| o o |"
|
||||
bone="+---------+"
|
||||
|
||||
|
||||
|
||||
# Functions
|
||||
|
||||
instructions () {
|
||||
|
||||
clear
|
||||
echo -n "Do you need instructions? (y/n) "; read ans
|
||||
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
|
||||
clear
|
||||
echo -e '\E[34;47m' # Blue type.
|
||||
|
||||
# "cat document"
|
||||
cat <<INSTRUCTIONSZZZ
|
||||
The name of the game is Petals Around the Rose,
|
||||
and that name is significant.
|
||||
Five dice will roll and you must guess the "answer" for each roll.
|
||||
It will be zero or an even number.
|
||||
After your guess, you will be told the answer for the roll, but . . .
|
||||
that's ALL the information you will get.
|
||||
|
||||
Six consecutive correct guesses admits you to the
|
||||
Fellowship of the Rose.
|
||||
INSTRUCTIONSZZZ
|
||||
|
||||
echo -e "\033[0m" # Turn off blue.
|
||||
else clear
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
fortune ()
|
||||
{
|
||||
RANGE=7
|
||||
FLOOR=0
|
||||
number=0
|
||||
while [ "$number" -le $FLOOR ]
|
||||
do
|
||||
number=$RANDOM
|
||||
let "number %= $RANGE" # 1 - 6.
|
||||
done
|
||||
|
||||
return $number
|
||||
}
|
||||
|
||||
|
||||
|
||||
throw () { # Calculate each individual die.
|
||||
fortune; B1=$?
|
||||
fortune; B2=$?
|
||||
fortune; B3=$?
|
||||
fortune; B4=$?
|
||||
fortune; B5=$?
|
||||
|
||||
calc () { # Function embedded within a function!
|
||||
case "$1" in
|
||||
3 ) rose=2;;
|
||||
5 ) rose=4;;
|
||||
* ) rose=0;;
|
||||
esac # Simplified algorithm.
|
||||
# Doesn't really get to the heart of the matter.
|
||||
return $rose
|
||||
}
|
||||
|
||||
answer=0
|
||||
calc "$B1"; answer=$(expr $answer + $(echo $?))
|
||||
calc "$B2"; answer=$(expr $answer + $(echo $?))
|
||||
calc "$B3"; answer=$(expr $answer + $(echo $?))
|
||||
calc "$B4"; answer=$(expr $answer + $(echo $?))
|
||||
calc "$B5"; answer=$(expr $answer + $(echo $?))
|
||||
}
|
||||
|
||||
|
||||
|
||||
game ()
|
||||
{ # Generate graphic display of dice throw.
|
||||
throw
|
||||
echo -e "\033[1m" # Bold.
|
||||
echo -e "\n"
|
||||
echo -e "$bone\t$bone\t$bone\t$bone\t$bone"
|
||||
echo -e \
|
||||
"${bone1[$B1]}\t${bone1[$B2]}\t${bone1[$B3]}\t${bone1[$B4]}\t${bone1[$B5]}"
|
||||
echo -e \
|
||||
"${bone2[$B1]}\t${bone2[$B2]}\t${bone2[$B3]}\t${bone2[$B4]}\t${bone2[$B5]}"
|
||||
echo -e \
|
||||
"${bone3[$B1]}\t${bone3[$B2]}\t${bone3[$B3]}\t${bone3[$B4]}\t${bone3[$B5]}"
|
||||
echo -e "$bone\t$bone\t$bone\t$bone\t$bone"
|
||||
echo -e "\n\n\t\t"
|
||||
echo -e "\033[0m" # Turn off bold.
|
||||
echo -n "There are how many petals around the rose? "
|
||||
}
|
||||
|
||||
|
||||
|
||||
# ============================================================== #
|
||||
|
||||
instructions
|
||||
|
||||
while [ "$petal" != "$EXIT" ] # Main loop.
|
||||
do
|
||||
game
|
||||
read petal
|
||||
echo "$petal" | grep [0-9] >/dev/null # Filter response for digit.
|
||||
# Otherwise just roll dice again.
|
||||
if [ "$?" -eq 0 ] # If-loop #1.
|
||||
then
|
||||
if [ "$petal" == "$answer" ]; then # If-loop #2.
|
||||
echo -e "\nCorrect. There are $petal petals around the rose.\n"
|
||||
(( hits++ ))
|
||||
|
||||
if [ "$hits" -eq "$WIN" ]; then # If-loop #3.
|
||||
echo -e '\E[31;47m' # Red type.
|
||||
echo -e "\033[1m" # Bold.
|
||||
echo "You have unraveled the mystery of the Rose Petals!"
|
||||
echo "Welcome to the Fellowship of the Rose!!!"
|
||||
echo "(You are herewith sworn to secrecy.)"; echo
|
||||
echo -e "\033[0m" # Turn off red & bold.
|
||||
break # Exit!
|
||||
else echo "You have $hits correct so far."; echo
|
||||
|
||||
if [ "$hits" -eq "$ALMOST" ]; then
|
||||
echo "Just one more gets you to the heart of the mystery!"; echo
|
||||
fi
|
||||
|
||||
fi # Close if-loop #3.
|
||||
|
||||
else
|
||||
echo -e "\nWrong. There are $answer petals around the rose.\n"
|
||||
hits=0 # Reset number of correct guesses.
|
||||
fi # Close if-loop #2.
|
||||
|
||||
echo -n "Hit ENTER for the next roll, or type \"exit\" to end. "
|
||||
read
|
||||
if [ "$REPLY" = "$EXIT" ]; then exit
|
||||
fi
|
||||
|
||||
fi # Close if-loop #1.
|
||||
|
||||
clear
|
||||
done # End of main (while) loop.
|
||||
|
||||
###
|
||||
|
||||
exit $?
|
||||
|
||||
# Resources:
|
||||
# ---------
|
||||
# 1) http://en.wikipedia.org/wiki/Petals_Around_the_Rose
|
||||
# (Wikipedia entry.)
|
||||
# 2) http://www.borrett.id.au/computing/petals-bg.htm
|
||||
# (How Bill Gates coped with the Petals Around the Rose challenge.)
|
|
@ -0,0 +1,462 @@
|
|||
#!/bin/bash
|
||||
# qky.sh
|
||||
|
||||
##############################################################
|
||||
# QUACKEY: a somewhat simplified version of Perquackey [TM]. #
|
||||
# #
|
||||
# Author: Mendel Cooper <thegrendel@theriver.com> #
|
||||
# version 0.1.02 03 May, 2008 #
|
||||
# License: GPL3 #
|
||||
##############################################################
|
||||
|
||||
WLIST=/usr/share/dict/word.lst
|
||||
# ^^^^^^^^ Word list file found here.
|
||||
# ASCII word list, one word per line, UNIX format.
|
||||
# A suggested list is the script author's "yawl" word list package.
|
||||
# http://ibiblio.org/pub/Linux/libs/yawl-0.3.2.tar.gz
|
||||
# or
|
||||
# http://personal.riverusers.com/~thegrendel/yawl-0.3.2.tar.gz
|
||||
|
||||
NONCONS=0 # Word not constructable from letter set.
|
||||
CONS=1 # Constructable.
|
||||
SUCCESS=0
|
||||
NG=1
|
||||
FAILURE=''
|
||||
NULL=0 # Zero out value of letter (if found).
|
||||
MINWLEN=3 # Minimum word length.
|
||||
MAXCAT=5 # Maximum number of words in a given category.
|
||||
PENALTY=200 # General-purpose penalty for unacceptable words.
|
||||
total=
|
||||
E_DUP=70 # Duplicate word error.
|
||||
|
||||
TIMEOUT=10 # Time for word input.
|
||||
|
||||
NVLET=10 # 10 letters for non-vulnerable.
|
||||
VULET=13 # 13 letters for vulnerable (not yet implemented).
|
||||
|
||||
declare -a Words
|
||||
declare -a Status
|
||||
declare -a Score=( 0 0 0 0 0 0 0 0 0 0 0 )
|
||||
|
||||
|
||||
letters=( a n s r t m l k p r b c i d s i d z e w u e t f
|
||||
e y e r e f e g t g h h i t r s c i t i d i j a t a o l a
|
||||
m n a n o v n w o s e l n o s p a q e e r a b r s a o d s
|
||||
t g t i t l u e u v n e o x y m r k )
|
||||
# Letter distribution table shamelessly borrowed from "Wordy" game,
|
||||
#+ ca. 1992, written by a certain fine fellow named Mendel Cooper.
|
||||
|
||||
declare -a LS
|
||||
|
||||
numelements=${#letters[@]}
|
||||
randseed="$1"
|
||||
|
||||
instructions ()
|
||||
{
|
||||
clear
|
||||
echo "Welcome to QUACKEY, the anagramming word construction game."; echo
|
||||
echo -n "Do you need instructions? (y/n) "; read ans
|
||||
|
||||
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
|
||||
clear
|
||||
echo -e '\E[31;47m' # Red foreground. '\E[34;47m' for blue.
|
||||
cat <<INSTRUCTION1
|
||||
|
||||
QUACKEY is a variant of Perquackey [TM].
|
||||
The rules are the same, but the scoring is simplified
|
||||
and plurals of previously played words are allowed.
|
||||
"Vulnerable" play is not yet implemented,
|
||||
but it is otherwise feature-complete.
|
||||
|
||||
As the game begins, the player gets 10 letters.
|
||||
The object is to construct valid dictionary words
|
||||
of at least 3-letter-length from the letterset.
|
||||
Each word-length category
|
||||
-- 3-letter, 4-letter, 5-letter, ... --
|
||||
fills up with the fifth word entered,
|
||||
and no further words in that category are accepted.
|
||||
|
||||
The penalty for too-short (two-letter), duplicate, unconstructable,
|
||||
and invalid (not in dictionary) words is -200. The same penalty applies
|
||||
to attempts to enter a word in a filled-up category.
|
||||
|
||||
INSTRUCTION1
|
||||
|
||||
echo -n "Hit ENTER for next page of instructions. "; read az1
|
||||
|
||||
cat <<INSTRUCTION2
|
||||
|
||||
The scoring mostly corresponds to classic Perquackey:
|
||||
The first 3-letter word scores 60, plus 10 for each additional one.
|
||||
The first 4-letter word scores 120, plus 20 for each additional one.
|
||||
The first 5-letter word scores 200, plus 50 for each additional one.
|
||||
The first 6-letter word scores 300, plus 100 for each additional one.
|
||||
The first 7-letter word scores 500, plus 150 for each additional one.
|
||||
The first 8-letter word scores 750, plus 250 for each additional one.
|
||||
The first 9-letter word scores 1000, plus 500 for each additional one.
|
||||
The first 10-letter word scores 2000, plus 2000 for each additional one.
|
||||
|
||||
Category completion bonuses are:
|
||||
3-letter words 100
|
||||
4-letter words 200
|
||||
5-letter words 400
|
||||
6-letter words 800
|
||||
7-letter words 2000
|
||||
8-letter words 10000
|
||||
This is a simplification of the absurdly complicated Perquackey bonus
|
||||
scoring system.
|
||||
|
||||
INSTRUCTION2
|
||||
|
||||
echo -n "Hit ENTER for final page of instructions. "; read az1
|
||||
|
||||
cat <<INSTRUCTION3
|
||||
|
||||
|
||||
Hitting just ENTER for a word entry ends the game.
|
||||
|
||||
Individual word entry is timed to a maximum of 10 seconds.
|
||||
*** Timing out on an entry ends the game. ***
|
||||
Other than that, the game is untimed.
|
||||
|
||||
--------------------------------------------------
|
||||
Game statistics are automatically saved to a file.
|
||||
--------------------------------------------------
|
||||
|
||||
For competitive ("duplicate") play, a previous letterset
|
||||
may be duplicated by repeating the script's random seed,
|
||||
command-line parameter \$1.
|
||||
For example, "qky 7633" specifies the letterset
|
||||
c a d i f r h u s k ...
|
||||
INSTRUCTION3
|
||||
|
||||
echo; echo -n "Hit ENTER to begin game. "; read az1
|
||||
|
||||
echo -e "\033[0m" # Turn off red.
|
||||
else clear
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
seed_random ()
|
||||
{ # Seed random number generator.
|
||||
if [ -n "$randseed" ] # Can specify random seed.
|
||||
then #+ for play in competitive mode.
|
||||
# RANDOM="$randseed"
|
||||
echo "RANDOM seed set to "$randseed""
|
||||
else
|
||||
randseed="$$" # Or get random seed from process ID.
|
||||
echo "RANDOM seed not specified, set to Process ID of script ($$)."
|
||||
fi
|
||||
|
||||
RANDOM="$randseed"
|
||||
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
get_letset ()
|
||||
{
|
||||
element=0
|
||||
echo -n "Letterset:"
|
||||
|
||||
for lset in $(seq $NVLET)
|
||||
do # Pick random letters to fill out letterset.
|
||||
LS[element]="${letters[$((RANDOM%numelements))]}"
|
||||
((element++))
|
||||
done
|
||||
|
||||
echo
|
||||
echo "${LS[@]}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
add_word ()
|
||||
{
|
||||
wrd="$1"
|
||||
local idx=0
|
||||
|
||||
Status[0]=""
|
||||
Status[3]=""
|
||||
Status[4]=""
|
||||
|
||||
while [ "${Words[idx]}" != '' ]
|
||||
do
|
||||
if [ "${Words[idx]}" = "$wrd" ]
|
||||
then
|
||||
Status[3]="Duplicate-word-PENALTY"
|
||||
let "Score[0]= 0 - $PENALTY"
|
||||
let "Score[1]-=$PENALTY"
|
||||
return $E_DUP
|
||||
fi
|
||||
|
||||
((idx++))
|
||||
done
|
||||
|
||||
Words[idx]="$wrd"
|
||||
get_score
|
||||
|
||||
}
|
||||
|
||||
get_score()
|
||||
{
|
||||
local wlen=0
|
||||
local score=0
|
||||
local bonus=0
|
||||
local first_word=0
|
||||
local add_word=0
|
||||
local numwords=0
|
||||
|
||||
wlen=${#wrd}
|
||||
numwords=${Score[wlen]}
|
||||
Score[2]=0
|
||||
Status[4]="" # Initialize "bonus" to 0.
|
||||
|
||||
case "$wlen" in
|
||||
3) first_word=60
|
||||
add_word=10;;
|
||||
4) first_word=120
|
||||
add_word=20;;
|
||||
5) first_word=200
|
||||
add_word=50;;
|
||||
6) first_word=300
|
||||
add_word=100;;
|
||||
7) first_word=500
|
||||
add_word=150;;
|
||||
8) first_word=750
|
||||
add_word=250;;
|
||||
9) first_word=1000
|
||||
add_word=500;;
|
||||
10) first_word=2000
|
||||
add_word=2000;; # This category modified from original rules!
|
||||
esac
|
||||
|
||||
((Score[wlen]++))
|
||||
if [ ${Score[wlen]} -eq $MAXCAT ]
|
||||
then # Category completion bonus scoring simplified!
|
||||
case $wlen in
|
||||
3 ) bonus=100;;
|
||||
4 ) bonus=200;;
|
||||
5 ) bonus=400;;
|
||||
6 ) bonus=800;;
|
||||
7 ) bonus=2000;;
|
||||
8 ) bonus=10000;;
|
||||
esac # Needn't worry about 9's and 10's.
|
||||
Status[4]="Category-$wlen-completion***BONUS***"
|
||||
Score[2]=$bonus
|
||||
else
|
||||
Status[4]="" # Erase it.
|
||||
fi
|
||||
|
||||
|
||||
let "score = $first_word + $add_word * $numwords"
|
||||
if [ "$numwords" -eq 0 ]
|
||||
then
|
||||
Score[0]=$score
|
||||
else
|
||||
Score[0]=$add_word
|
||||
fi # All this to distinguish last-word score
|
||||
#+ from total running score.
|
||||
let "Score[1] += ${Score[0]}"
|
||||
let "Score[1] += ${Score[2]}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
get_word ()
|
||||
{
|
||||
local wrd=''
|
||||
read -t $TIMEOUT wrd # Timed read.
|
||||
echo $wrd
|
||||
}
|
||||
|
||||
is_constructable ()
|
||||
{ # This was the most complex and difficult-to-write function.
|
||||
local -a local_LS=( "${LS[@]}" ) # Local copy of letter set.
|
||||
local is_found=0
|
||||
local idx=0
|
||||
local pos
|
||||
local strlen
|
||||
local local_word=( "$1" )
|
||||
strlen=${#local_word}
|
||||
|
||||
while [ "$idx" -lt "$strlen" ]
|
||||
do
|
||||
is_found=$(expr index "${local_LS[*]}" "${local_word:idx:1}")
|
||||
if [ "$is_found" -eq "$NONCONS" ] # Not constructable!
|
||||
then
|
||||
echo "$FAILURE"; return
|
||||
else
|
||||
((pos = ($is_found - 1) / 2)) # Compensate for spaces betw. letters!
|
||||
local_LS[pos]=$NULL # Zero out used letters.
|
||||
((idx++)) # Bump index.
|
||||
fi
|
||||
done
|
||||
|
||||
echo "$SUCCESS"
|
||||
return
|
||||
}
|
||||
|
||||
is_valid ()
|
||||
{ # Surprisingly easy to check if word in dictionary ...
|
||||
fgrep -qw "$1" "$WLIST" # ... thanks to 'grep' ...
|
||||
echo $?
|
||||
}
|
||||
|
||||
check_word ()
|
||||
{
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
Status[1]=""
|
||||
Status[2]=""
|
||||
Status[3]=""
|
||||
Status[4]=""
|
||||
|
||||
iscons=$(is_constructable "$1")
|
||||
if [ "$iscons" ]
|
||||
then
|
||||
Status[1]="constructable"
|
||||
v=$(is_valid "$1")
|
||||
if [ "$v" -eq "$SUCCESS" ]
|
||||
then
|
||||
Status[2]="valid"
|
||||
strlen=${#1}
|
||||
|
||||
if [ ${Score[strlen]} -eq "$MAXCAT" ] # Category full!
|
||||
then
|
||||
Status[3]="Category-$strlen-overflow-PENALTY"
|
||||
return $NG
|
||||
fi
|
||||
|
||||
case "$strlen" in
|
||||
1 | 2 )
|
||||
Status[3]="Two-letter-word-PENALTY"
|
||||
return $NG;;
|
||||
* )
|
||||
Status[3]=""
|
||||
return $SUCCESS;;
|
||||
esac
|
||||
else
|
||||
Status[3]="Not-valid-PENALTY"
|
||||
return $NG
|
||||
fi
|
||||
else
|
||||
Status[3]="Not-constructable-PENALTY"
|
||||
return $NG
|
||||
fi
|
||||
|
||||
### FIXME: Streamline the above code.
|
||||
|
||||
}
|
||||
|
||||
|
||||
display_words ()
|
||||
{
|
||||
local idx=0
|
||||
local wlen0
|
||||
|
||||
clear
|
||||
echo "Letterset: ${LS[@]}"
|
||||
echo "Threes: Fours: Fives: Sixes: Sevens: Eights:"
|
||||
echo "------------------------------------------------------------"
|
||||
|
||||
|
||||
|
||||
while [ "${Words[idx]}" != '' ]
|
||||
do
|
||||
wlen0=${#Words[idx]}
|
||||
case "$wlen0" in
|
||||
3) ;;
|
||||
4) echo -n " " ;;
|
||||
5) echo -n " " ;;
|
||||
6) echo -n " " ;;
|
||||
7) echo -n " " ;;
|
||||
8) echo -n " " ;;
|
||||
esac
|
||||
echo "${Words[idx]}"
|
||||
((idx++))
|
||||
done
|
||||
|
||||
### FIXME: The word display is pretty crude.
|
||||
}
|
||||
|
||||
|
||||
play ()
|
||||
{
|
||||
word="Start game" # Dummy word, to start ...
|
||||
|
||||
while [ "$word" ] # If player just hits return (blank word),
|
||||
do #+ then game ends.
|
||||
echo "$word: "${Status[@]}""
|
||||
echo -n "Last score: [${Score[0]}] TOTAL score: [${Score[1]}]: Next word: "
|
||||
total=${Score[1]}
|
||||
word=$(get_word)
|
||||
check_word "$word"
|
||||
|
||||
if [ "$?" -eq "$SUCCESS" ]
|
||||
then
|
||||
add_word "$word"
|
||||
else
|
||||
let "Score[0]= 0 - $PENALTY"
|
||||
let "Score[1]-=$PENALTY"
|
||||
fi
|
||||
|
||||
display_words
|
||||
done # Exit game.
|
||||
|
||||
### FIXME: The play () function calls too many other functions.
|
||||
### This is perilously close to "spaghetti code" ...
|
||||
}
|
||||
|
||||
end_of_game ()
|
||||
{ # Save and display stats.
|
||||
|
||||
#######################Autosave##########################
|
||||
savefile=qky.save.$$
|
||||
# ^^ PID of script
|
||||
echo `date` >> $savefile
|
||||
echo "Letterset # $randseed (random seed) ">> $savefile
|
||||
echo -n "Letterset: " >> $savefile
|
||||
echo "${LS[@]}" >> $savefile
|
||||
echo "---------" >> $savefile
|
||||
echo "Words constructed:" >> $savefile
|
||||
echo "${Words[@]}" >> $savefile
|
||||
echo >> $savefile
|
||||
echo "Score: $total" >> $savefile
|
||||
|
||||
echo "Statistics for this round saved in \""$savefile"\""
|
||||
#########################################################
|
||||
|
||||
echo "Score for this round: $total"
|
||||
echo "Words: ${Words[@]}"
|
||||
}
|
||||
|
||||
# ---------#
|
||||
instructions
|
||||
seed_random
|
||||
get_letset
|
||||
play
|
||||
end_of_game
|
||||
# ---------#
|
||||
|
||||
exit $?
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# 1) Clean up code!
|
||||
# 2) Prettify the display_words () function (maybe with widgets?).
|
||||
# 3) Improve the time-out ... maybe change to untimed entry,
|
||||
#+ but with a time limit for the overall round.
|
||||
# 4) An on-screen countdown timer would be nice.
|
||||
# 5) Implement "vulnerable" mode of play.
|
||||
# 6) Improve save-to-file capability (and maybe make it optional).
|
||||
# 7) Fix bugs!!!
|
|
@ -26,3 +26,6 @@ adr=${1:-`whoami`} # Default to current user, if not specified.
|
|||
echo "At `date`, script \"`basename $0`\" mailed to "$adr"."
|
||||
|
||||
exit 0
|
||||
|
||||
# Note that the "mailx" command (in "send" mode) may be substituted
|
||||
#+ for "mail" ... but with somewhat different options.
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
# TMOUT=3 Also works, as of newer versions of Bash.
|
||||
|
||||
|
||||
TIMELIMIT=3 # Three seconds in this instance. May be set to different value.
|
||||
TIMER_INTERRUPT=14
|
||||
TIMELIMIT=3 # Three seconds in this instance.
|
||||
# May be set to different value.
|
||||
|
||||
PrintAnswer()
|
||||
{
|
||||
|
@ -13,28 +14,30 @@ PrintAnswer()
|
|||
echo $answer
|
||||
else # Don't want to mix up the two instances.
|
||||
echo "Your favorite veggie is $answer"
|
||||
kill $! # Kills no longer needed TimerOn function running in background.
|
||||
# $! is PID of last job running in background.
|
||||
kill $! # Kills no-longer-needed TimerOn function
|
||||
#+ running in background.
|
||||
# $! is PID of last job running in background.
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
TimerOn()
|
||||
{
|
||||
sleep $TIMELIMIT && kill -s 14 $$ &
|
||||
# Waits 3 seconds, then sends sigalarm to script.
|
||||
}
|
||||
|
||||
|
||||
Int14Vector()
|
||||
{
|
||||
answer="TIMEOUT"
|
||||
PrintAnswer
|
||||
exit 14
|
||||
exit $TIMER_INTERRUPT
|
||||
}
|
||||
|
||||
trap Int14Vector 14 # Timer interrupt (14) subverted for our purposes.
|
||||
trap Int14Vector $TIMER_INTERRUPT
|
||||
# Timer interrupt (14) subverted for our purposes.
|
||||
|
||||
echo "What is your favorite vegetable "
|
||||
TimerOn
|
||||
|
@ -42,12 +45,14 @@ read answer
|
|||
PrintAnswer
|
||||
|
||||
|
||||
# Admittedly, this is a kludgy implementation of timed input,
|
||||
#+ however the "-t" option to "read" simplifies this task.
|
||||
# See "t-out.sh", below.
|
||||
# Admittedly, this is a kludgy implementation of timed input.
|
||||
# However, the "-t" option to "read" simplifies this task.
|
||||
# See the "t-out.sh" script.
|
||||
# However, what about timing not just single user input,
|
||||
#+ but an entire script?
|
||||
|
||||
# If you need something really elegant...
|
||||
# If you need something really elegant ...
|
||||
#+ consider writing the application in C or C++,
|
||||
#+ using appropriate library functions, such as 'alarm' and 'setitimer'.
|
||||
#+ using appropriate library functions, such as 'alarm' and 'setitimer.'
|
||||
|
||||
exit 0
|
||||
|
|
Loading…
Reference in New Issue