mirror of https://github.com/tLDP/LDP
new
This commit is contained in:
parent
77c6f1f451
commit
9a5932bc1e
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
# agram.sh: Playing games with anagrams.
|
||||
|
||||
# Find anagrams of...
|
||||
LETTERSET=etaoinshrdlu
|
||||
|
||||
anagram "$LETTERSET" | # Find all anagrams of the letterset...
|
||||
grep '.......' | # With at least 7 letters,
|
||||
grep '^is' | # starting with 'is'
|
||||
grep -v 's$' | # no plurals
|
||||
grep -v 'ed$' # no past tense verbs
|
||||
|
||||
# Uses "anagram" utility
|
||||
#+ that is part of the author's "yawl" word list package.
|
||||
# http://ibiblio.org/pub/Linux/libs/yawl-0.2.tar.gz
|
||||
|
||||
exit 0 # End of code.
|
||||
|
||||
bash$ sh agram.sh
|
||||
islander
|
||||
isolate
|
||||
isolead
|
||||
isotheral
|
|
@ -0,0 +1,119 @@
|
|||
#!/bin/bash
|
||||
# cannon.sh: Approximating PI by firing cannonballs.
|
||||
|
||||
# This is a very simple instance of a "Monte Carlo" simulation,
|
||||
#+ a mathematical model of a real-life event,
|
||||
#+ using pseudorandom numbers to emulate random chance.
|
||||
|
||||
# Consider a perfectly square plot of land, 10000 units on a side.
|
||||
# This land has a perfectly circular lake in its center,
|
||||
#+ with a diameter of 10000 units.
|
||||
# The plot is actually all water, except for the four corners.
|
||||
# (Think of it as a square with an inscribed circle.)
|
||||
#
|
||||
# Let us fire solid iron cannonballs from an old-style cannon
|
||||
#+ at the square of land.
|
||||
# All the shots impact somewhere on the plot of land,
|
||||
#+ either in the lake or on the dry corners.
|
||||
# Since the lake takes up most of the land area,
|
||||
#+ most of the shots will SPLASH! into the water.
|
||||
# Just a few shots will THUD! into solid ground
|
||||
#+ in the far corners of the land.
|
||||
#
|
||||
# If we take enough random, unaimed shots at the plot of land,
|
||||
#+ Then the ratio of SPLASHES to total shots will approximate
|
||||
#+ the value of PI/4
|
||||
# Exercise: Explain why.
|
||||
#
|
||||
# Theoretically, the more shots taken, the better the fit.
|
||||
# However, a shell script, as opposed to a compiled language
|
||||
#+ with floating-point math built in, requires a few compromises.
|
||||
# This tends to make the simulation less accurate, unfortunately.
|
||||
|
||||
|
||||
DIMENSION=10000 # Length of each side of the plot of land.
|
||||
# Also sets ceiling for random integers generated.
|
||||
|
||||
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.
|
||||
|
||||
get_random ()
|
||||
{
|
||||
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')
|
||||
RANDOM=$SEED # From "seeding-random.sh"
|
||||
#+ example script.
|
||||
let "rnum = $RANDOM % $DIMENSION" # Range less than 10000.
|
||||
echo $rnum
|
||||
}
|
||||
|
||||
distance= # Declare global variable.
|
||||
hypotenuse () # Calculate hypotenuse of a right triangle.
|
||||
{ # From "alt-bc.sh" example.
|
||||
distance=$(bc -l << EOF
|
||||
scale = 0
|
||||
sqrt ( $1 * $1 + $2 * $2 )
|
||||
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.
|
||||
}
|
||||
|
||||
|
||||
# main() {
|
||||
|
||||
# Initialize variables.
|
||||
shots=0
|
||||
splashes=0
|
||||
thuds=0
|
||||
Pi=0
|
||||
|
||||
while [ "$shots" -lt "$MAXSHOTS" ] # Main loop.
|
||||
do
|
||||
|
||||
xCoord=$(get_random) # Get random X and Y coords.
|
||||
yCoord=$(get_random)
|
||||
hypotenuse $xCoord $yCoord # Hypotenuse of right-triangle =
|
||||
#+ distance.
|
||||
((shots++))
|
||||
|
||||
printf "#%4d " $shots
|
||||
printf "Xc = %4d " $xCoord
|
||||
printf "Yc = %4d " $yCoord
|
||||
printf "Distance = %5d " $distance # Distance from center
|
||||
#+ of lake.
|
||||
|
||||
if [ "$distance" -le "$DIMENSION" ]
|
||||
then
|
||||
echo -n "SPLASH! "
|
||||
((splashes++))
|
||||
else
|
||||
echo -n "THUD! "
|
||||
((thuds++))
|
||||
fi
|
||||
|
||||
Pi=$(echo "scale=9; $PMULTIPLIER*$splashes/$shots" | bc)
|
||||
# Multiply ratio by 4.0.
|
||||
echo -n "PI ~ $Pi"
|
||||
echo
|
||||
|
||||
done
|
||||
|
||||
echo
|
||||
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.
|
||||
echo
|
||||
|
||||
# }
|
||||
|
||||
exit 0
|
||||
|
||||
# One might well wonder whether a shell script is appropriate for
|
||||
#+ an application as complex and computation-intensive as a simulation.
|
||||
#
|
||||
# There are at least two justifications.
|
||||
# 1) As a proof of concept: to show it can be done.
|
||||
# 2) To prototype and test the algorithms before rewriting
|
||||
#+ it in a compiled high-level language.
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/bash
|
||||
# color-echo.sh: Echoing text messages in color.
|
||||
|
||||
# Modify this script for your own purposes.
|
||||
# It's easier than hand-coding color.
|
||||
|
||||
black='\E[30;47m'
|
||||
red='\E[31;47m'
|
||||
green='\E[32;47m'
|
||||
yellow='\E[33;47m'
|
||||
blue='\E[34;47m'
|
||||
magenta='\E[35;47m'
|
||||
cyan='\E[36;47m'
|
||||
white='\E[37;47m'
|
||||
|
||||
|
||||
alias Reset="tput sgr0" # Reset text attributes to normal
|
||||
#+ without clearing screen.
|
||||
|
||||
|
||||
cecho () # Color-echo.
|
||||
# Argument $1 = message
|
||||
# Argument $1 = color
|
||||
{
|
||||
local default_msg="No message passed."
|
||||
# Doesn't really need to be a local variable.
|
||||
|
||||
message=${1:-$default_msg} # Defaults to default message.
|
||||
color=${2:-$black} # Defaults to black, if not specified.
|
||||
|
||||
echo -e "$color"
|
||||
echo "$message"
|
||||
Reset # Reset to normal.
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Now, let's try it out.
|
||||
# ----------------------------------------------------
|
||||
cecho "Feeling blue..." $blue
|
||||
cecho "Magenta looks more like purple." $magenta
|
||||
cecho "Green with envy." $green
|
||||
cecho "Seeing red?" $red
|
||||
cecho "Cyan, more familiarly known as aqua." $cyan
|
||||
cecho "No color passed (defaults to black)."
|
||||
# Missing $color argument.
|
||||
cecho "\"Empty\" color passed (defaults to black)." ""
|
||||
# Empty $color argument.
|
||||
cecho
|
||||
# Missing $message and $color arguments.
|
||||
cecho "" ""
|
||||
# Empty $message and $color arguments.
|
||||
# ----------------------------------------------------
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
||||
# Exercises:
|
||||
# ---------
|
||||
# 1) Add the "bold" attribute to the 'cecho ()' function.
|
||||
# 2) Add options for colored backgrounds.
|
|
@ -0,0 +1,75 @@
|
|||
#!/bin/bash
|
||||
# ex30a.sh: "Colorized" version of ex30.sh.
|
||||
# Crude address database
|
||||
|
||||
|
||||
clear # Clear the screen.
|
||||
|
||||
echo -n " "
|
||||
echo -e '\E[37;44m'"\033[1mContact List\033[0m"
|
||||
# White on blue background
|
||||
echo; echo
|
||||
echo -e "\033[1mChoose one of the following persons:\033[0m"
|
||||
# Bold
|
||||
tput sgr0
|
||||
echo "(Enter only the first letter of name.)"
|
||||
echo
|
||||
echo -en '\E[47;34m'"\033[1mE\033[0m" # Blue
|
||||
tput sgr0 # Reset colors to "normal."
|
||||
echo "vans, Roland" # "[E]vans, Roland"
|
||||
echo -en '\E[47;35m'"\033[1mJ\033[0m" # Magenta
|
||||
tput sgr0
|
||||
echo "ones, Mildred"
|
||||
echo -en '\E[47;32m'"\033[1mS\033[0m" # Green
|
||||
tput sgr0
|
||||
echo "mith, Julie"
|
||||
echo -en '\E[47;31m'"\033[1mZ\033[0m" # Red
|
||||
tput sgr0
|
||||
echo "ane, Morris"
|
||||
echo
|
||||
|
||||
read person
|
||||
|
||||
case "$person" in
|
||||
# Note variable is quoted.
|
||||
|
||||
"E" | "e" )
|
||||
# Accept upper or lowercase input.
|
||||
echo
|
||||
echo "Roland Evans"
|
||||
echo "4321 Floppy Dr."
|
||||
echo "Hardscrabble, CO 80753"
|
||||
echo "(303) 734-9874"
|
||||
echo "(303) 734-9892 fax"
|
||||
echo "revans@zzy.net"
|
||||
echo "Business partner & old friend"
|
||||
;;
|
||||
|
||||
"J" | "j" )
|
||||
echo
|
||||
echo "Mildred Jones"
|
||||
echo "249 E. 7th St., Apt. 19"
|
||||
echo "New York, NY 10009"
|
||||
echo "(212) 533-2814"
|
||||
echo "(212) 533-9972 fax"
|
||||
echo "milliej@loisaida.com"
|
||||
echo "Girlfriend"
|
||||
echo "Birthday: Feb. 11"
|
||||
;;
|
||||
|
||||
# Add info for Smith & Zane later.
|
||||
|
||||
* )
|
||||
# Default option.
|
||||
# Empty input (hitting RETURN) fits here, too.
|
||||
echo
|
||||
echo "Not yet in database."
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
tput sgr0 # Reset colors to "normal."
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
# poem.sh
|
||||
|
||||
# Lines of the poem (single stanza).
|
||||
Line[1]="I do not know which to prefer,"
|
||||
Line[2]="The beauty of inflections"
|
||||
Line[3]="Or the beauty of innuendoes,"
|
||||
Line[4]="The blackbird whistling"
|
||||
Line[5]="Or just after."
|
||||
|
||||
# Attribution.
|
||||
Attrib[1]=" Wallace Stevens"
|
||||
Attrib[2]="\"Thirteen Ways of Looking at a Blackbird\""
|
||||
|
||||
for index in 1 2 3 4 5 # Five lines.
|
||||
do
|
||||
printf " %s\n" "${Line[index]}"
|
||||
done
|
||||
|
||||
for index in 1 2 # Two attribution lines.
|
||||
do
|
||||
printf " %s\n" "${Attrib[index]}"
|
||||
done
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
# self-source.sh: a script sourcing itself "recursively."
|
||||
# From "Stupid Script Tricks," Volume II.
|
||||
|
||||
MAXPASSCNT=100 # Maximum number of execution passes.
|
||||
|
||||
echo -n "$pass_count "
|
||||
# At first execution pass, this just echoes two blank spaces,
|
||||
#+ since $pass_count still uninitialized.
|
||||
|
||||
let "pass_count += 1"
|
||||
# Assumes the uninitialized variable $pass_count
|
||||
#+ can be incremented the first time around.
|
||||
# This works with Bash and pdksh, but
|
||||
#+ it relies on non-portable (and possibly dangerous) behavior.
|
||||
# Better would be to set $pass_count to 0 if non-initialized.
|
||||
|
||||
while [ "$pass_count" -le $MAXPASSCNT ]
|
||||
do
|
||||
. $0 # Script "sources" itself, rather than calling itself.
|
||||
# ./$0 (which would be true recursion) doesn't work here.
|
||||
done
|
||||
|
||||
# What occurs here is not actually recursion,
|
||||
#+ since the script effectively "expands" itself
|
||||
#+ (generates a new section of code)
|
||||
#+ with each pass throught the 'while' loop',
|
||||
# with each 'source' in line 20.
|
||||
#
|
||||
# Of course, the script interprets each newly 'sourced' "#!" line
|
||||
#+ as a comment, and not as the start of a new script.
|
||||
|
||||
echo
|
||||
|
||||
exit 0 # The net effect is counting from 1 to 100.
|
||||
# Very impressive.
|
||||
|
||||
# Exercise:
|
||||
# --------
|
||||
# Write a script that uses this trick to do something useful.
|
|
@ -0,0 +1,157 @@
|
|||
#!/bin/bash
|
||||
# soundex.sh: Calculate "soundex" code for names
|
||||
|
||||
# =======================================================
|
||||
# Soundex script
|
||||
# by
|
||||
# Mendel Cooper
|
||||
# thegrendel@theriver.com
|
||||
# 23 January, 2002
|
||||
#
|
||||
# Placed in the Public Domain.
|
||||
#
|
||||
# A slightly different version of this script appeared in
|
||||
#+ Ed Schaefer's July, 2002 "Shell Corner" column
|
||||
#+ in "Unix Review" on-line,
|
||||
#+ http://www.unixreview.com/documents/uni1026336632258/
|
||||
# =======================================================
|
||||
|
||||
|
||||
ARGCOUNT=1 # Need name as argument.
|
||||
E_WRONGARGS=70
|
||||
|
||||
if [ $# -ne "$ARGCOUNT" ]
|
||||
then
|
||||
echo "Usage: `basename $0` name"
|
||||
exit $E_WRONGARGS
|
||||
fi
|
||||
|
||||
|
||||
assign_value () # Assigns numerical value
|
||||
{ #+ to letters of name.
|
||||
|
||||
val1=bfpv # 'b,f,p,v' = 1
|
||||
val2=cgjkqsxz # 'c,g,j,k,q,s,x,z' = 2
|
||||
val3=dt # etc.
|
||||
val4=l
|
||||
val5=mn
|
||||
val6=r
|
||||
|
||||
# Exceptionally clever use of 'tr' follows.
|
||||
# Try to figure out what is going on here.
|
||||
|
||||
value=$( echo "$1" \
|
||||
| tr -d wh \
|
||||
| tr $val1 1 | tr $val2 2 | tr $val3 3 \
|
||||
| tr $val4 4 | tr $val5 5 | tr $val6 6 \
|
||||
| tr -s 123456 \
|
||||
| tr -d aeiouy )
|
||||
|
||||
# Assign letter values.
|
||||
# Remove duplicate numbers, except when separated by vowels.
|
||||
# Ignore vowels, except as separators, so delete them last.
|
||||
# Ignore 'w' and 'h', even as separators, so delete them first.
|
||||
#
|
||||
# The above command substitution lays more pipe than a plumber <g>.
|
||||
|
||||
}
|
||||
|
||||
|
||||
input_name="$1"
|
||||
echo
|
||||
echo "Name = $input_name"
|
||||
|
||||
|
||||
# Change all characters of name input to lowercase.
|
||||
# ------------------------------------------------
|
||||
name=$( echo $input_name | tr A-Z a-z )
|
||||
# ------------------------------------------------
|
||||
# Just in case argument to script is mixed case.
|
||||
|
||||
|
||||
# Prefix of soundex code: first letter of name.
|
||||
# --------------------------------------------
|
||||
|
||||
|
||||
char_pos=0 # Initialize character position.
|
||||
prefix0=${name:$char_pos:1}
|
||||
prefix=`echo $prefix0 | tr a-z A-Z`
|
||||
# Uppercase 1st letter of soundex.
|
||||
|
||||
let "char_pos += 1" # Bump character position to 2nd letter of name.
|
||||
name1=${name:$char_pos}
|
||||
|
||||
|
||||
# ++++++++++++++++++++++++++ Exception Patch +++++++++++++++++++++++++++++++++
|
||||
# Now, we run both the input name and the name shifted one char to the right
|
||||
#+ through the value-assigning function.
|
||||
# If we get the same value out, that means that the first two characters
|
||||
#+ of the name have the same value assigned, and that one should cancel.
|
||||
# However, we also need to test whether the first letter of the name
|
||||
#+ is a vowel or 'w' or 'h', because otherwise this would bollix things up.
|
||||
|
||||
char1=`echo $prefix | tr A-Z a-z` # First letter of name, lowercased.
|
||||
|
||||
assign_value $name
|
||||
s1=$value
|
||||
assign_value $name1
|
||||
s2=$value
|
||||
assign_value $char1
|
||||
s3=$value
|
||||
s3=9$s3 # If first letter of name is a vowel
|
||||
#+ or 'w' or 'h',
|
||||
#+ then its "value" will be null (unset).
|
||||
#+ Therefore, set it to 9, an otherwise
|
||||
#+ unused value, which can be tested for.
|
||||
|
||||
|
||||
if [[ "$s1" -ne "$s2" || "$s3" -eq 9 ]]
|
||||
then
|
||||
suffix=$s2
|
||||
else
|
||||
suffix=${s2:$char_pos}
|
||||
fi
|
||||
# ++++++++++++++++++++++ end Exception Patch +++++++++++++++++++++++++++++++++
|
||||
|
||||
|
||||
padding=000 # Use at most 3 zeroes to pad.
|
||||
|
||||
|
||||
soun=$prefix$suffix$padding # Pad with zeroes.
|
||||
|
||||
MAXLEN=4 # Truncate to maximum of 4 chars.
|
||||
soundex=${soun:0:$MAXLEN}
|
||||
|
||||
echo "Soundex = $soundex"
|
||||
|
||||
echo
|
||||
|
||||
# The soundex code is a method of indexing and classifying names
|
||||
#+ by grouping together the ones that sound alike.
|
||||
# The soundex code for a given name is the first letter of the name,
|
||||
#+ followed by a calculated three-number code.
|
||||
# Similar sounding names should have almost the same soundex codes.
|
||||
|
||||
# Examples:
|
||||
# Smith and Smythe both have a "S-530" soundex.
|
||||
# Harrison = H-625
|
||||
# Hargison = H-622
|
||||
# Harriman = H-655
|
||||
|
||||
# This works out fairly well in practice, but there are numerous anomalies.
|
||||
#
|
||||
#
|
||||
# The U.S. Census and certain other governmental agencies use soundex,
|
||||
# as do genealogical researchers.
|
||||
#
|
||||
# For more information,
|
||||
#+ see the "National Archives and Records Administration home page",
|
||||
#+ http://www.nara.gov/genealogy/soundex/soundex.html
|
||||
|
||||
|
||||
|
||||
# Exercise:
|
||||
# --------
|
||||
# Simplify the "Exception Patch" section of this script.
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
# tempfile-name.sh: temp filename generator
|
||||
|
||||
BASE_STR=`mcookie` # 32-character magic cookie.
|
||||
POS=11 # Arbitrary position in magic cookie string.
|
||||
LEN=5 # Get $LEN consecutive characters.
|
||||
|
||||
prefix=temp # This is, after all, a "temp" file.
|
||||
# For more "uniqueness," generate the filename prefix
|
||||
#+ using the same method as the suffix, below.
|
||||
|
||||
suffix=${BASE_STR:POS:LEN}
|
||||
# Extract a 5-character string, starting at position 11.
|
||||
|
||||
temp_filename=$prefix.$suffix
|
||||
# Construct the filename.
|
||||
|
||||
echo "Temp filename = "$temp_filename""
|
||||
|
||||
# sh tempfile-name.sh
|
||||
# Temp filename = temp.e19ea
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
# unit-conversion.sh
|
||||
|
||||
|
||||
convert_units () # Takes as arguments the units to convert.
|
||||
{
|
||||
cf=$(units "$1" "$2" | sed --silent -e '1p' | awk '{print $2}')
|
||||
# Strip off everything except the actual conversion factor.
|
||||
echo "$cf"
|
||||
}
|
||||
|
||||
Unit1=miles
|
||||
Unit2=meters
|
||||
cfactor=`convert_units $Unit1 $Unit2`
|
||||
quantity=3.73
|
||||
|
||||
result=$(echo $quantity*$cfactor | bc)
|
||||
|
||||
echo "There are $result $Unit2 in $quantity $Unit1."
|
||||
|
||||
# What happens if you pass incompatible units,
|
||||
#+ such as "acres" and "miles" to the function?
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
# usage-message.sh
|
||||
|
||||
: ${1?"Usage: $0 ARGUMENT"}
|
||||
# Script exits here if command-line parameter absent,
|
||||
#+ with following error message.
|
||||
# usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
|
||||
|
||||
echo "These two lines echo only if command-line parameter given."
|
||||
echo "command line parameter = \"$1\""
|
||||
|
||||
exit 0 # Will exit here only if command-line parameter present.
|
||||
|
||||
# Check the exit status, both with and without command-line parameter.
|
||||
# If command-line parameter present, then "$?" is 0.
|
||||
# If not, then "$?" is 1.
|
Loading…
Reference in New Issue