diff --git a/LDP/guide/docbook/abs-guide/Change.log b/LDP/guide/docbook/abs-guide/Change.log index 2a4065aa..10376e4e 100644 --- a/LDP/guide/docbook/abs-guide/Change.log +++ b/LDP/guide/docbook/abs-guide/Change.log @@ -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 diff --git a/LDP/guide/docbook/abs-guide/INDEX00.sgml b/LDP/guide/docbook/abs-guide/INDEX00.sgml index d6bbb9fd..6bbf44c0 100644 --- a/LDP/guide/docbook/abs-guide/INDEX00.sgml +++ b/LDP/guide/docbook/abs-guide/INDEX00.sgml @@ -11,9 +11,23 @@ ^ (caret) - Beginning-of-line, in a Regular Expression + + + + Beginning-of-line, + in a Regular Expression + + + + ^ + ^^ + Uppercase + conversion in parameter + substitution + + + ~ Tilde @@ -233,9 +247,8 @@ command ;; Double-semicolon, terminator in a - case option + case option - Required when ... do keyword is on the first line of @@ -245,6 +258,11 @@ code block + ;;& ;& + Terminators in + a case option (version 4+ of Bash). + : @@ -342,7 +360,19 @@ quoting , - Comma operator + + + Comma operator + + + , + ,, + Lowercase + conversion in parameter + substitution + + + @@ -618,6 +648,12 @@ arithmetic operator + + ** + Extended globbing + file-match operator + + @@ -769,6 +805,8 @@ Arrays + Associative arrays + Bracket notation Concatenating, @@ -881,6 +919,8 @@ Version 2 Version 3 + + Version 4 @@ -931,6 +971,10 @@ Extended, {a..z} + With increment and + zero-padding (new feature in Bash, version + 4) @@ -1029,6 +1073,10 @@ Command-line options + command_not_found_handle () + builtin error-handling function + (version 4+ of Bash) + Command substitution @@ -1100,6 +1148,7 @@ + Coprocesses cron, scheduling daemon C-style syntax @@ -1167,8 +1216,11 @@ declare builtin - options + + options + case-modification + options (version 4+ of Bash) + Default parameters @@ -1285,6 +1337,9 @@ references Risk of using + Using + eval to select among + variables Evaluation of @@ -1496,6 +1551,8 @@ linkend="cryptoquote">Crypto-Quotes Dealing a deck of cards + Fifteen Puzzle Horse race Podcasting Poem Towers of Hanoi + linkend="hanoi">Towers of Hanoi + Graphic + version + Alternate graphic + version + getopt, @@ -1549,6 +1611,9 @@ dot files + Golden Ratio + (Phi) + -ge , greater-than or equal integer comparison test @@ -1608,6 +1673,8 @@ Here strings + Calculating the Golden + Ratio Prepending text Using read @@ -1911,6 +1978,8 @@ + mapfile builtin, + loads an array with a text file Math commands Meta-meaning @@ -2019,6 +2088,11 @@ parameter + + Case modification + (version 4+ of + Bash). + Script example Table @@ -2161,7 +2235,9 @@ echo to a loop echo - to read + to read (however, this problem + can be circumvented) + tail to grep @@ -2180,6 +2256,9 @@ Variables in a subshell, scope limited + Subshell in while-read + loop Whitespace, misuse of @@ -2297,6 +2376,10 @@ command Template + while-read loop + without a + subshell Prompt @@ -2427,6 +2510,8 @@ construct + readline library + Recursion Special characters - Stack, emulating a push-down, example - script + + Stack + + Definition + Emulating a push-down stack, + example script + + Standard Deviation, example script Startup files, Bash @@ -3089,7 +3180,12 @@ Testing a variable to see if it contains only digits Tracking script usage + linkend="trackingscr">Tracking script + usage + while-read loop + without a + subshell Widgets, invoking from a script @@ -3288,9 +3384,14 @@ conditions Omitting test brackets - - while read - construct + + + while read + construct + + Avoiding a + subshell + Whitespace, diff --git a/LDP/guide/docbook/abs-guide/abs-guide.sgml b/LDP/guide/docbook/abs-guide/abs-guide.sgml index 3f8d2ad8..5fd693c5 100644 --- a/LDP/guide/docbook/abs-guide/abs-guide.sgml +++ b/LDP/guide/docbook/abs-guide/abs-guide.sgml @@ -97,7 +97,6 @@ - @@ -199,7 +198,6 @@ - @@ -298,6 +296,8 @@ + + @@ -334,6 +334,7 @@ + @@ -354,6 +355,10 @@ + + + + @@ -361,6 +366,7 @@ + @@ -384,21 +390,14 @@ - 5.6 - 26 January 2009 + 6.0.05 + 24 March 2009 978-1-4357-5219-1 - - 5.4 - 21 July 2008 - mc - 'ANGLEBERRY' release: Major Update. - - 5.5 23 Nov 2008 @@ -413,6 +412,13 @@ 'WORCESTERBERRY' release: Minor Update. + + 6.0 + 23 Mar 2009 + mc + 'THIMBLEBERRY' release: Minor Update. + + @@ -472,7 +478,7 @@ - Why Shell Programming? + Shell Programming! No programming language is perfect. There is not even a single @@ -1158,6 +1164,35 @@ esac + + ;;& + ;& + + ;;& + + + special character + ;;& + + + ;& + case statement + + + ;& + + + <link + linkend="ncterm">Terminators</link> + in a <firstterm>case</firstterm> option (<link + linkend="bash4ref">version 4+</link> of Bash). + + + + + + + . . @@ -1336,8 +1371,8 @@ esac - The comma operator can also - concatenate strings. + The comma + operator can also concatenate strings. for file in /{,usr/}bin/*calc # ^ Find all executable files ending in "calc" #+ in /bin and /usr/bin directories. @@ -1358,8 +1393,22 @@ done + + + , + , + + <link linkend="casemodparamsub">Lowercase + conversion</link> in <firstterm>parameter substitution</firstterm> + (added in <link + linkend="bash4ref">version 4</link> of Bash) + + + + + \ <link linkend="escp">escape</link> [backslash] @@ -1507,8 +1556,8 @@ fi target file (: >> target_file). If the file did not previously exist, creates it. - This applies to regular files, not pipes, - symlinks, and certain special files. + This applies to regular files, + not pipes, symlinks, and certain special files. May be used to begin a comment line, although this is not @@ -1645,9 +1694,10 @@ fi - A double asterisk, **, is the exponentiation - operator. + ** A double asterisk can represent the + exponentiation + operator or extended + file-match globbing. @@ -1950,14 +2000,18 @@ echo "a = $a" # a = 123 {xxx,yyy,zzz,...} Brace expansion - cat {file1,file2,file3} > combined_file + +echo \"{These,words,are,quoted}\" # " prefix and suffix +# "These" "words" "are" "quoted" + + +cat {file1,file2,file3} > combined_file # Concatenates the files file1, file2, and file3 into combined_file. - cp file22.{txt,backup} -# Copies "file22.txt" to "file22.backup" - +# Copies "file22.txt" to "file22.backup" + A command may act upon a comma-separated list of file specs within braces. @@ -3060,6 +3114,10 @@ echo $z # 2 beginning of line + + uppercase modification + parameter substitution + beginning-of-line @@ -3071,6 +3129,18 @@ echo $z # 2 + + ^ + ^^ + + <link linkend="casemodparamsub">Uppercase + conversion</link> in <firstterm>parameter substitution</firstterm> + (added in <link + linkend="bash4ref">version 4</link> of Bash) + + + + Control Characters @@ -6593,6 +6663,7 @@ echo "t2 = $t2 a = $a" # t2 = 5 a = 9 + $BASH_SUBSHELL @@ -6610,6 +6681,54 @@ echo "t2 = $t2 a = $a" # t2 = 5 a = 9 + + + $BASHPID + + $BASHPID + + + variable + process ID + + Process ID + of the current instance of Bash. This is not the same as the + $$ variable, but it often + gives the same result. + + +bash4$ echo $$ +11015 + + +bash4$ echo $BASHPID +11015 + + +bash4$ ps ax | grep bash4 +11015 pts/2 R 0:00 bash4 + + + But ... + +#!/bin/bash4 + +echo "\$\$ outside of subshell = $$" # 9602 +echo "\$BASH_SUBSHELL outside of subshell = $BASH_SUBSHELL" # 0 +echo "\$BASHPID outside of subshell = $BASHPID" # 9602 + +echo + +( echo "\$\$ inside of subshell = $$" # 9602 + echo "\$BASH_SUBSHELL inside of subshell = $BASH_SUBSHELL" # 1 + echo "\$BASHPID inside of subshell = $BASHPID" ) # 9603 + # Note that $$ returns PID of parent process. + + + + + $BASH_VERSINFO[n] @@ -6691,6 +6810,18 @@ done stack The top value in the directory stack + + + A stack register + is a set of consecutive memory locations, such that + the values stored (pushed) + are retrieved (popped) + in reverse order. The last + value stored is the first retrieved. This is + sometimes called a LIFO + (last-in-first-out) or + pushdown stack. + (affected by pushd and popd) This builtin variable corresponds to the dirs @@ -8051,14 +8182,21 @@ echo $_ # : PID of script - Process ID of the script itself. The - $$ variable often finds use - in scripts to construct unique - temp file names (see , , , and ). This is usually simpler than - invoking mktemp. - + Process ID (PID) of + the script itself. + + Within a script, inside a subshell, + $$ returns + the PID of the script, not the + subshell. + + The $$ variable often + finds use in scripts to construct unique + temp file names (see , , and ). + This is usually simpler than invoking mktemp. + @@ -8281,6 +8419,7 @@ echo ${stringZ: -4} # Cabc &randstring; + If the $string parameter is * or @, then this extracts a maximum @@ -10400,24 +10539,29 @@ done  "$condition2" )  command  ;; - esac + esac - Quoting the variables is not mandatory, since - word splitting does not take place. + Quoting the variables is not mandatory, + since word splitting does not take place. Each test line ends with a right paren ). - Each condition block ends with a double - semicolon ;;. + Each condition block ends + with a double semicolon + ;;. - The entire case block terminates with an - esac (case spelled - backwards). + If a condition tests + true, then the associated + commands execute and the case + block terminates. + The entire case + block ends with an esac + (case spelled backwards). @@ -11126,6 +11270,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment. comm command compress + coproc cp cpio cron @@ -11264,6 +11409,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment. make MAKEDEV man + mapfile mcookie md5sum merge @@ -11301,6 +11447,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment. patch (Related topic: diff) pathchk + pax pgrep pidof ping @@ -11840,6 +11987,10 @@ echo; echo "Keypress was "\"$keypress\""." permits timed input (see and ). + The option + takes the file descriptor + of the target file. + The read command may also read its variable value from a file @@ -12018,10 +12169,12 @@ while read f; do bookmark - This command set is a mechanism for bookmarking working directories, - a means of moving back and forth through directories in an orderly - manner. A pushdown stack is used to keep track of directory names. - Options allow various manipulations of the directory stack. + This command set is a mechanism for bookmarking + working directories, a means of moving back and forth + through directories in an orderly manner. A pushdown stack is used to keep track + of directory names. Options allow various manipulations + of the directory stack. pushd dir-name pushes the path @@ -12107,14 +12260,28 @@ while read f; do eval arg1 [arg2] ... [argN] Combines the arguments in an expression or list of - expressions and evaluates them. Any - variables contained within the expression are expanded. The - result translates into a command. This can be useful for - code generation from the command-line or within a script. - + expressions and evaluates them. + Any variables within the expression are expanded. The + net result is to convert a string into a + command. + + The eval command can be used for + code generation from the command-line or within a script. + +bash$ command_string=xterm +bash$ eval $command_string +Filesystem 1K-blocks Used Available Use% Mounted on + /dev/sda5 1904920 590204 1217952 33% / + /dev/sda9 5409672 892396 4517276 17% /home + /dev/sda1 18431244 13244376 5186868 72% /media/hd + /dev/sda7 10142384 7812496 1814676 82% /usr + /dev/sda8 1138428 258964 821632 24% /var + + + bash$ process=xterm bash$ show_process="eval ps ax | grep $process" bash$ $show_process @@ -12147,6 +12314,13 @@ eval eval echo $a # d &ex43; + + + Using <firstterm>eval</firstterm> to select + among variables + &arrchoice; + + <firstterm>Echoing</firstterm> the <firstterm>command-line parameters</firstterm> @@ -12919,8 +13093,9 @@ done variable $PATH - Record the path name of specified commands -- in the - shell hash table + Records the path + name of specified commands -- in the shell hash + table @@ -12932,19 +13107,19 @@ done algorithms (methods, or recipes). - An advantage of hashing is that it - is fast. A disadvantage is that collisions -- - where a single key maps to more than one data item -- are - possible. + An advantage of hashing is that + it is fast. A disadvantage is that + collisions -- where a single key + maps to more than one data item -- are possible. For examples of hashing see and . - -- so the shell or script will not need to search - the $PATH on subsequent calls to those + -- so the shell or script will not need to search the + $PATH on subsequent calls to those commands. When hash is called with no - arguments, it simply lists the commands that have been hashed. + arguments, it simply lists the commands that have been hashed. The option resets the hash table. @@ -12963,9 +13138,10 @@ done The bind builtin displays or modifies readline - The readline library - is what Bash uses for reading input in an interactive - shell. + The + readline library is what + Bash uses for reading input in an + interactive shell. key bindings. @@ -12984,7 +13160,9 @@ done Gets a short usage summary of a shell builtin. This is the counterpart to whatis, - but for builtins. + but for builtins. The display of help + information got a much-needed update in the version 4 release of Bash. bash$ help exit @@ -16516,6 +16694,44 @@ function write_utf8_string { + + pax + + pax + + + command + archive + + + + The pax + portable archive + exchange toolkit + facilitates periodic file backups and is designed + to be cross-compatible between various flavors of UNIX. + It was ported from BSD to Linux. + + + pax -wf daily_backup.pax ~/linux-server/files +# Creates a tar archive of all files in the target directory. +# Note that the options to pax must be in the correct order -- +#+ pax -fw has an entirely different effect. + +pax -f daily_backup.pax +# Lists the files in the archive. + +pax -rf daily_backup.pax ~/bsd-server/files +# Restores the backed-up files from the Linux machine +#+ onto a BSD one. + + + Note that pax handles many of + the standard archiving and compression commands. + + + + @@ -18215,8 +18431,8 @@ fi Utility and protocol for uploading / downloading files to or from a remote host. An ftp session can be automated - in a script (see , , and ). + in a script (see and ). @@ -18979,13 +19195,21 @@ LIMIT_STRING The dc (desk - calculator) utility is stack-oriented + calculator) utility is stack-oriented and uses RPN (Reverse Polish Notation). Like bc, it has much of the power of a programming language. - Most persons avoid dc, since it - requires non-intuitive input. Yet, it has its uses. + + echo "7 8 * p" | dc # 56 +# Pushes 7, then 8 onto the stack, +#+ multiplies ("*" operator), then prints the result ("p" operator). + + + Most persons avoid dc, because + of its non-intuitive input and rather cryptic + operators. Yet, it has its uses. Converting a decimal number to hexadecimal @@ -19004,6 +19228,18 @@ LIMIT_STRING + + dc <<< 10k5v1+2/p # 1.6180339887 +# ^^^ Feed operations to dc using a Here String. +# ^^^ Pushes 10 and sets that as the precision (10k). +# ^^ Pushes 5 and takes its square root (5v, v = square root). +# ^^ Pushes 1 and adds it to the running total (1+). +# ^^ Pushes 2 and divides the running total by that (2/). +# ^ Pops and prints the result (p) +# The result is 1.6180339887 ... +# ... which happens to be the Pythagorean Golden Ratio, to 10 places. + + Factoring &factr; @@ -23124,12 +23360,22 @@ then #+ Prevent other programs & scripts of system resources. Usually invoked with the option, which sets a limit on file size (ulimit -f 1000 limits files to 1 meg - maximum). The option limits the coredump + maximum). + As of the version + 4 update of Bash, the + and options take a block size + of 512 when in POSIX + mode. Additionally, there are two new options: + for socket buffer size, and + for the limit on the number of + threads. + The option limits the coredump size (ulimit -c 0 eliminates coredumps). - Normally, the value of ulimit - would be set in /etc/profile - and/or ~/.bash_profile (see ). + Normally, the value of ulimit + would be set in /etc/profile + and/or ~/.bash_profile (see ). @@ -24335,11 +24581,12 @@ then # POSIX char class Bash does carry out filename expansion - Filename expansion means - expanding filename patterns or templates containing special - characters. For example, example.??? might - expand to example.001 and/or - example.txt. + Filename expansion + means expanding filename patterns or templates + containing special characters. For example, + example.??? might expand + to example.001 and/or + example.txt. -- a process known as globbing -- but this does not use the standard RE set. @@ -24834,7 +25081,9 @@ echo "Seventh word in String is: ${Words[6]}" # (null) Exercise: Find other uses for here - strings. + strings, such as, for example, feeding input to + dc. @@ -24870,7 +25119,7 @@ echo "Seventh word in String is: ${Words[6]}" # (null) to keep track of it. Consider it a simplified type of file pointer. It is analogous to a file handle in - C. + C. The file descriptors for stdin, stdout, and stderr are @@ -24933,6 +25182,8 @@ echo "Seventh word in String is: ${Words[6]}" # (null) #+ stdout and stderr to file "filename" -- #+ fails with the error message, #+ syntax error near unexpected token `>'. + # The &>> operator is supposed to be functional in Bash 4, + #+ but as of version 4.0 still is not. M>N # "M" is a file descriptor, which defaults to 1, if not explicitly set. @@ -24972,6 +25223,14 @@ echo "Seventh word in String is: ${Words[6]}" # (null) 2>&1 # Redirects stderr to stdout. # Error messages get sent to same place as standard output. + >>filename 2>&1 + bad_command >>filename 2>&1 + # Appends both stdout and stderr to the file "filename" ... + 2>&1 | [command(s)] + bad_command 2>&1 | awk '{print $5}' # found + # Sends stderr through a pipe. + # |& was added to Bash 4 as an abbreviation for 2>& + #+ but as of version 4.0 this still does not work. i>&j # Redirects file descriptor i to j. @@ -25081,8 +25340,9 @@ ls -yz 2>&1 >> command.log - Child processes inherit open file descriptors. This is why pipes - work. To prevent an fd from being inherited, close it. + + Child processes inherit open file descriptors. This is + why pipes work. To prevent an fd from being inherited, close it. # Redirecting only stderr to a pipe. exec 3>&1 # Save current "value" of stdout. @@ -25358,11 +25618,10 @@ but is shown here for illustrative purposes. An external command invoked with an exec does not (usually) fork off a subprocess / subshell. - whereas a Bash builtin does not. For this reason, - builtins execute more quickly than their external command - equivalents. - + whereas a Bash builtin + does not. For this reason, builtins execute more quickly + and use fewer system resources than their external command + equivalents. @@ -25391,7 +25650,8 @@ but is shown here for illustrative purposes. Variable scope in a subshell &subshell; - See also . + See also $BASHPID and + . @@ -25518,10 +25778,17 @@ fi operator, as in ls -al | (command). - A command block between curly - braces does not launch - a subshell. - { command1; command2; command3; . . . commandN; } + + A code block between curly brackets does + not launch a subshell. + { command1; command2; command3; . . . commandN; } + var1=23 +echo "$var1" # 23 + +{ var1=76; } +echo "$var1" # 76 + @@ -25738,6 +26005,15 @@ exec 3>&- # Thanks, Stéphane Chazelas + Here is a method of circumventing the + problem of an echo + piped to a while-read loop running + in a subshell. + + + Code block redirection without forking + &wrps; + A reader sent in the following interesting example of process substitution. @@ -26528,6 +26804,7 @@ exit 0 # This script will not exit normally. &hanoi; + @@ -26994,7 +27271,7 @@ echo $element_count # 8 -- Arrays permit deploying old familiar algorithms as shell scripts. - Whether this is necessarily a good idea is left to the reader to + Whether this is necessarily a good idea is left for the reader to decide. @@ -28113,6 +28390,20 @@ trap 'echo "Control-C disabled."' 2 + + + brace expansion + Enable + brace + expansion (default setting = + on) + + + + brace expansion + Disable + brace expansion + noclobber @@ -28141,6 +28432,16 @@ trap 'echo "Control-C disabled."' 2 (none) Read commands from ... + + + + Informs user of any open jobs upon shell exit. + Introduced in version 4 + of Bash, and still experimental. + Usage: shopt -s checkjobs + (Caution: may hang!) + errexit @@ -28156,6 +28457,16 @@ trap 'echo "Control-C disabled."' 2 noglob Filename expansion (globbing) disabled + + + globbing + star-match + Enables the ** globbing operator + (version 4+ of Bash). + Usage: shopt -s globstar + interactive @@ -28725,11 +29036,14 @@ find $HOME -type f -atime +30 -size 100k | { - A related problem occurs when trying to write the + A lookalike problem occurs when trying to write the stdout of a tail -f piped to grep. tail -f /var/log/messages | grep "$ERROR_MSG" >> error.log -# The "error.log" file will not have anything written to it. +# The "error.log" file will not have anything written to it. +# As Samuli Kaipiainen points out, this results from grep +#+ buffering its output. +# The fix is to add the "--line-buffered" parameter to grep. @@ -30534,6 +30848,15 @@ echo "User entered: "$answer"" $( ) notation + + Brace expansion + + + + Certain array operations, + and associative arrays + + The double brackets extended test construct @@ -30562,6 +30885,10 @@ echo "User entered: "$answer"" Bash-specific builtins + + Coprocesses + + @@ -30597,7 +30924,7 @@ echo "User entered: "$answer"" - Bash, versions 2 and 3 + Bash, versions 2, 3, and 4 Bash, version 2 @@ -30606,22 +30933,17 @@ echo "User entered: "$answer"" The current version of Bash, the one - you have running on your machine, is most likely version 2.xx.yy - or 3.xx.yy. + you have running on your machine, is most likely version 2.xx.yy, + 3.xx.yy, or 4.xx.yy. bash$ echo $BASH_VERSION 3.2.25(1)-release The version 2 update of the classic Bash scripting language - added array variables, - - Chet Ramey has promised associative arrays - (a nifty Perl feature) in a future Bash release. As of version - 3.2, this has not yet happened. - - string and parameter expansion, and a better method - of indirect variable references, among other features. + added array variables, string and parameter expansion, and + a better method of indirect variable references, among other + features. String expansion @@ -30685,8 +31007,10 @@ echo # Or just . . . echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z +echo {e..m} # e f g h i j k l m echo {z..a} # z y x w v u t s r q p o n m l k j i h g f e d c b a # Works backwards, too. +echo {25..30} # 25 26 27 28 29 30 echo {3..-2} # 3 2 1 0 -1 -2 echo {X..d} # X Y Z [ ] ^ _ ` a b c d # Shows (some of) the ASCII characters between Z and a, @@ -30695,8 +31019,24 @@ echo {]..a} # {]..a} # Why? +# You can tack on prefixes and suffixes. +echo "Number #"{1..4}, "..." + # Number #1, Number #2, Number #3, Number #4, ... -# Unfortunately, this does not lend itself to parameterization. + +# You can concatenate brace-expansion sets. +echo {1..3}{x..z}" +" "..." + # 1x + 1y + 1z + 2x + 2y + 2z + 3x + 3y + 3z + ... + # Generates an algebraic expression. + # This could be used to find permutations. + +# You can nest brace-expansion sets. +echo {{a..c},{1..3}} + # a b c 1 2 3 + # The "comma operator" splices together strings. + + +# Unfortunately, brace expansion does not lend itself to parameterization. var1=1 var2=5 echo {$var1..$var2} # {1..5} @@ -30802,8 +31142,7 @@ fi scripts to make sure they still work! As it happens, a couple of the scripts in the Advanced Bash Scripting Guide had to be - fixed up (see - and , for instance). + fixed up (see , for instance). @@ -30886,15 +31225,17 @@ echo $a # 6 In fact, quoting in this context is not advisable as it may cause regex evaluation to fail. - See the Bash + FAQ that quoting explicitly disables regex evaluation. + See also the - Ubuntu Bug List - and and Wikinerds on Bash syntax. - With Bash version 3.2.25(1), running on Fedora Core, - quoting still works, but do not assume this will be the case on - your machine. + + Setting shopt -s compat31 + in a script causes reversion to the original + behavior. @@ -30904,11 +31245,396 @@ echo $a # 6 - - - + + + + Bash, version 4 + + + Chet Ramey announced Version 4 of Bash on the 20th + of February, 2009. This release has a number of significant + new features, as well as some important bugfixes. + + Among the new goodies: + + + + + Associative arrays. + + An associative array can + be thought of as a set of two linked arrays -- one holding + the data, and the other the + keys that index the individual elements + of the data array. + + + + A simple address database + &fetchaddress; + + + + A somewhat more elaborate address database + &fetchaddress2; + + + + + Enhancements to the + case construct: + the ;;& and + ;& terminators. + + + Testing characters + &case4; + + + + + The new coproc + builtin enables two parallel processes to communicate and + interact. As Chet Ramey states in the + Bash FAQ + Copyright 1995-2009 by Chester Ramey. + , ver. 4.01: + + +
+ + There is a new 'coproc' reserved word that specifies a coprocess: + an asynchronous command run with two pipes connected to the creating + shell. Coprocs can be named. The input and output file descriptors + and the PID of the coprocess are available to the calling shell in + variables with coproc-specific names. + +
+ + Coprocesses use file descriptors. + File descriptors enable processes and + pipes to communicate. + + #!/bin/bash4 +# A coprocess communicates with a while-read loop. + +coproc cat $0 +while read -u ${COPROC[0]} line # ${COPROC[0]} is the +do #+ file descriptor of the coprocess. + echo "$line" | sed -e 's/line/NOT-ORIGINAL-TEXT/' +done + +kill $COPROC_PID # No longer need the coprocess, + #+ so kill its PID. + + But, be careful! + + #!/bin/bash4 + +echo; echo +a=aaa +b=bbb +c=ccc + +coproc echo "one two three" +while read -u ${COPROC[0]} a b c; # Note that this loop +do #+ runs in a subshell. + echo "Inside while-read loop: "; + echo "a = $a"; echo "b = $b"; echo "c = $c" + echo "coproc file descriptor: ${COPROC[0]}" +done + +# a = one +# b = two +# c = three +# So far, so good, but ... + +echo "-----------------" +echo "Outside while-read loop: " +echo "a = $a" # a = +echo "b = $b" # b = +echo "c = $c" # c = +echo "coproc file descriptor: ${COPROC[0]}" +echo +# The coproc is still running, but ... +#+ it still doesn't enable the parent process +#+ to "inherit" variables from the child process, the while-read loop. + +# Compare this to the "badread.sh" script. + + + The coprocess is asynchronous, + and this might cause a problem. It may terminate before another + process has finished communicating with it. + + #!/bin/bash4 + +coproc cpname { for i in {0..10}; do echo "index = $i"; done; } +# ^^^^^^ This is a *named* coprocess. +read -u ${cpname[0]} +echo $REPLY # index = 0 +echo ${COPROC[0]} #+ No output ... the coprocess timed out + # after the first loop iteration. + + +
+ + + + The new mapfile + builtin makes it possible to load an array with the contents + of a text file without using a loop or command substitution. + + #!/bin/bash4 + +mapfile Arr1 < $0 +# Same result as Arr1=( $(cat $0) ) +echo "${Arr1[@]}" # Copies this entire script out to stdout. + +echo "--"; echo + +# But, not the same as read -a !!! +read -a Arr2 < $0 +echo "${Arr2[@]}" # Reads only first line of script into the array. + +exit + + + + + The read builtin got + a minor facelift. The + timeout option now accepts + (decimal) fractional values + This only works with pipes and certain other + special files. + and the option + permits preloading the edit buffer. + But only in conjunction with + readline, i.e., + from the command-line. + Unfortunately, these enhancements are still a work in progress + and not (yet) usable in scripts. + + + + + Parameter substitution + gets case-modification operators. + +#!/bin/bash4 + +var=veryMixedUpVariable +echo ${var} # veryMixedUpVariable +echo ${var^} # VeryMixedUpVariable +# * First char --> uppercase. +echo ${var^^} # VERYMIXEDUPVARIABLE +# ** All chars --> uppercase. +echo ${var,} # veryMixedUpVariable +# * First char --> lowercase. +echo ${var,,} # verymixedupvariable +# ** All chars --> lowercase. + + + + + The declare builtin now + accepts the lowercase + and capitalize + options. + +#!/bin/bash4 + +declare -l var1 # Will change to lowercase +var1=MixedCaseVARIABLE +echo "$var1" # mixedcasevariable +# Same effect as echo $var1 | tr A-Z a-z + +declare -c var2 # Changes only initial char to uppercase. +var2=originally_lowercase +echo "$var2" # Originally_lowercase +# NOT the same effect as echo $var2 | tr a-z A-Z + + + + + Brace expansion has more options. + + Increment/decrement, specified in the + final term within braces. + #!/bin/bash4 + +echo {40..60..2} +# 40 42 44 46 48 50 52 54 56 58 60 +# All the even numbers, between 40 and 60. + +echo {60..40..2} +# 60 58 56 54 52 50 48 46 44 42 40 +# All the even numbers, between 40 and 60, counting backwards. +# In effect, a decrement. +echo {60..40..-2} +# The same output. The minus sign is not necessary. + +# But, what about letters and symbols? +echo {X..d} +# X Y Z [ ] ^ _ ` a b c d +echo {X..d..2} +# X Z ^ ` b d +# It seems to work for upper/lowercase letters, +#+ but the increment is a bit inconsistent on symbols. + + Zero-padding, specified in the + first term within braces, prefixes each term in the output + with the same number of zeroes. + + +bash4$ echo {010..15} +010 011 012 013 014 015 + + +bash4$ echo {000..10} +000 001 002 003 004 005 006 007 008 009 010 + + + + + + + Substring + extraction on positional + parameters now starts with $0 as the + zero-index. (This corrects an + inconsistency in the treatment of positional parameters.) + + #!/bin/bash4 +# show-params.bash4 + +# Invoke this scripts with at least one positional parameter. + +E_BADPARAMS=99 + +if [ -z "$1" ] +then + echo "Usage $0 param1 ..." + exit $E_BADPARAMS +fi + +echo ${@:0} + +# bash3 show-params.bash4 one two three +# one two three + +# bash4 show-params.bash4 one two three +# show-params.bash4 one two three + +# $0 $1 $2 $3 + + + + + The new ** + globbing operator + matches filenames and directories + recursively. + + #!/bin/bash4 +# filelist.bash4 + +shopt -s globstar # Must enable globstar, otherwise ** doesn't work. + # The globstar shell option is new to version 4 of Bash. + +echo "Using *"; echo +for filename in * +do + echo "$filename" +done # Lists only files in current directory ($PWD). + +echo; echo "--------------"; echo + +echo "Using **" +for filename in ** +do + echo "$filename" +done # Lists complete file tree, recursively. + +exit + +Using * + +allmyfiles +filelist.bash4 + +-------------- + +Using ** + +allmyfiles +allmyfiles/file.index.txt +allmyfiles/my_music +allmyfiles/my_music/me-singing-60s-folksongs.ogg +allmyfiles/my_music/me-singing-opera.ogg +allmyfiles/my_music/piano-lesson.1.ogg +allmyfiles/my_pictures +allmyfiles/my_pictures/at-beach-with-Jade.png +allmyfiles/my_pictures/picnic-with-Melissa.png +filelist.bash4 + + + + + The new $BASHPID + internal variable. + + + + + There is a new builtin + error-handling function named + command_not_found_handle. + #!/bin/bash4 + +command_not_found_handle () +{ # Accepts implicit parameters. + echo "The following command is not valid: \""$1\""" + echo "With the following argument(s): \""$2\"" \""$3\""" # $4, $5 ... +} # $1, $2, etc. are not explicitly passed to the function. + +bad_command arg1 arg2 + +# The following command is not valid: "bad_command" +# With the following argument(s): "arg1" "arg2" + + +
+ + + Editorial comment + Associative arrays? Coprocesses? Whatever happened + to the lean and mean Bash we have come to know and love? + Could it be suffering from (horrors!) feature + creep? Or perhaps even Korn shell envy? + Note to Chet Ramey: Please add only + essential features in future Bash + releases -- perhaps for-each + loops and support for multi-dimensional arrays. Most + Bash users won't need, won't use, and likely won't greatly + appreciate complex features like built-in debuggers, + Perl interfaces, and bolt-on rocket boosters. + + + +
+ + + + + @@ -30967,7 +31693,10 @@ echo $a # 6 special qualifications, In fact, he is a school dropout and has no formal credentials or qualifications - whatsoever. + whatsoever. Aside from the ABS Guide, + his main claim to fame is a First Place in the sack + race at the Colfax Elementary School Field Day in June, + 1958. other than a compulsion to write. Those who can, do. Those who can't . . . get an MCSE. @@ -31235,9 +31964,9 @@ echo $a # 6 Benno Schulenberg, Tedman Eng, Jochen DeSmet, Juan Nicolas Ruiz, Oliver Beckstein, Achmed Darwish, Dotan Barak, Richard Neill, Albert Siersema, Omair Eshkenazi, Geoff Lee, JuanJo Ciarlante, - Cliff Bamford, Nathan Coulter, Antonio Macchi, Andreas Kühne, - Pádraig Brady, and David Lawyer (himself an author of - four HOWTOs). + Cliff Bamford, Nathan Coulter, Antonio Macchi, Tomas Pospisek, + Andreas Kühne, Pádraig Brady, and David Lawyer + (himself an author of four HOWTOs). My gratitude to Chet Ramey and Brian Fox for writing Bash, @@ -31584,7 +32313,7 @@ echo $a # 6 1973 0-691-02356-5 - The classic tutorial on problem solving methods + The classic tutorial on problem-solving methods (i.e., algorithms), with special emphasis on how to teach them. * @@ -31818,9 +32547,17 @@ echo $a # 6 - Chet Ramey's Bash FAQ.. - This site carries the latest version of the FAQ. + Chet Ramey's Bash FAQ, + and mirror + site. + + + + + + + Greg's WIKI: Bash FAQ. @@ -31872,6 +32609,14 @@ echo $a # 6 + + + Example shell scripts at joyent. + + + + Steve Parker's + + + An excellent collection of Bash scripting tips, tricks, + and resources at the Bash Hackers + Wiki. + + + Giles Orr's + + + Shelltris and shellitaire + at Shell Script + Games. + + + Mark Komarinski's + + + The Wikipedia + article covering dc. + + + The manpages for @@ -32239,7 +33009,7 @@ echo $a # 6 +++ - The following two scripts are by Mark Moraes of the University + The following script is by Mark Moraes of the University of Toronto. See the file Moraes-COPYRIGHT for permissions and restrictions. This file is included in the combined HTML/source tarball @@ -32251,11 +33021,6 @@ echo $a # 6 &behead; - - <firstterm>ftpget</firstterm>: Downloading files via ftp - &ftpget; - - + Antek Sawicki contributed the following script, which makes very @@ -32335,11 +33100,6 @@ echo $a # 6 Stéphane Chazelas demonstrates object-oriented programming in a Bash script. - - Object-oriented database - &objoriented; - - Mariusz Gniazdowski contributed a hash library for use in scripts. @@ -32514,6 +33274,25 @@ echo $a # 6 &msquare; + + Fifteen Puzzle + &fifteen; + + + + + <firstterm>The Towers of Hanoi, graphic + version</firstterm> + &hanoi2; + + + + + <firstterm>The Towers of Hanoi, alternate graphic + version</firstterm> + &hanoi2a; + + An alternate version of the <link linkend="getoptsimple">getopt-simple.sh</link> script @@ -36707,6 +37486,11 @@ thegrendel@theriver.com 26 Jan 2009 WORCESTERBERRY release: Minor update. + + + 23 Mar 2009 + THIMBLEBERRY release: Major update. + @@ -36723,7 +37507,7 @@ thegrendel@theriver.com bzip2-ed tarball including both the SGML source and rendered HTML, may be downloaded from the author's + url="http://bash.neuralshortcircuit.com/abs-guide-latest.tar.bz2">author's home site). A 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. + */ diff --git a/LDP/guide/docbook/abs-guide/case4.sh b/LDP/guide/docbook/abs-guide/case4.sh new file mode 100644 index 00000000..3da68d1d --- /dev/null +++ b/LDP/guide/docbook/abs-guide/case4.sh @@ -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. diff --git a/LDP/guide/docbook/abs-guide/copy-cd.sh b/LDP/guide/docbook/abs-guide/copy-cd.sh index dc8c320a..debec553 100644 --- a/LDP/guide/docbook/abs-guide/copy-cd.sh +++ b/LDP/guide/docbook/abs-guide/copy-cd.sh @@ -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" ... diff --git a/LDP/guide/docbook/abs-guide/ex40.sh b/LDP/guide/docbook/abs-guide/ex40.sh index 88141dfb..568542bc 100644 --- a/LDP/guide/docbook/abs-guide/ex40.sh +++ b/LDP/guide/docbook/abs-guide/ex40.sh @@ -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 diff --git a/LDP/guide/docbook/abs-guide/ex72.sh b/LDP/guide/docbook/abs-guide/ex72.sh index 536c4ea0..72542ec1 100644 --- a/LDP/guide/docbook/abs-guide/ex72.sh +++ b/LDP/guide/docbook/abs-guide/ex72.sh @@ -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 diff --git a/LDP/guide/docbook/abs-guide/fetch_address-2.sh b/LDP/guide/docbook/abs-guide/fetch_address-2.sh new file mode 100644 index 00000000..6d94adf3 --- /dev/null +++ b/LDP/guide/docbook/abs-guide/fetch_address-2.sh @@ -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. diff --git a/LDP/guide/docbook/abs-guide/fetch_address.sh b/LDP/guide/docbook/abs-guide/fetch_address.sh new file mode 100644 index 00000000..7cae768f --- /dev/null +++ b/LDP/guide/docbook/abs-guide/fetch_address.sh @@ -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. diff --git a/LDP/guide/docbook/abs-guide/fifteen.sh b/LDP/guide/docbook/abs-guide/fifteen.sh new file mode 100644 index 00000000..9b2fad42 --- /dev/null +++ b/LDP/guide/docbook/abs-guide/fifteen.sh @@ -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. diff --git a/LDP/guide/docbook/abs-guide/hanoi2.bash b/LDP/guide/docbook/abs-guide/hanoi2.bash new file mode 100644 index 00000000..75cfde4d --- /dev/null +++ b/LDP/guide/docbook/abs-guide/hanoi2.bash @@ -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. diff --git a/LDP/guide/docbook/abs-guide/hanoi2a.bash b/LDP/guide/docbook/abs-guide/hanoi2a.bash new file mode 100644 index 00000000..5c4de22e --- /dev/null +++ b/LDP/guide/docbook/abs-guide/hanoi2a.bash @@ -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. diff --git a/LDP/guide/docbook/abs-guide/ind-ref.sh b/LDP/guide/docbook/abs-guide/ind-ref.sh index 476558aa..c235faad 100644 --- a/LDP/guide/docbook/abs-guide/ind-ref.sh +++ b/LDP/guide/docbook/abs-guide/ind-ref.sh @@ -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 diff --git a/LDP/guide/docbook/abs-guide/wr-ps.bash b/LDP/guide/docbook/abs-guide/wr-ps.bash new file mode 100644 index 00000000..ada8f8f4 --- /dev/null +++ b/LDP/guide/docbook/abs-guide/wr-ps.bash @@ -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 $?