123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #!/bin/bash
-
- #
- # Bottles of Beer song in Bash
- #
- # A way-overcomplicated implementation of the bottles of beer song in bash.
- # Optional argument:
- #
- # * `--careless` - Generate the "happen to fall" version
- #
- # NOTE: This is an altered version of a "99 bottles of beer" song
- # Bash script by Bill Brown. The intent of the altered version is
- # to show the style, so the above text is preserved from [the
- # original][99b].
- #
- # [99b]: http://99-bottles-of-beer.net/language-bash-1831.html
- #
-
- standardBreakLine="Take one down and pass it around"
- wastefulBreakLine="If one of those bottles should happen to fall"
- breakLine=$([ "$1" = --careless ] \
- && echo $wastefulBreakLine \
- || echo $standardBreakLine)
-
- pred() { #get predecessor to a number
- case $1 in
- *nine) echo ${1%nine}eight;;
- *eight) echo ${1%eight}seven;;
- *seven) echo ${1%seven}six;;
- *six) echo ${1%six}five;;
- *five) echo ${1%five}four;;
- *four) echo ${1%four}three;;
- *three) echo ${1%three}two;;
- *two) echo ${1%two}one;;
- one) echo zero;;
- *-one) echo ${1%-one};;
- *one) echo ${1%one};;
- ten) echo nine;;
- eleven) echo ten;;
- twelve) echo eleven;;
- *teen) teenpred $1;;
- *ty) tenspred $1;;
- zero) echo ""; #to terminate
- esac
- }
-
- teenpred() { #predecessor of a teen
- case $1 in
- thirteen) echo twelve;;
- *) echo $(crunchprefix $(pred $(uncrunchprefix ${1%teen})))teen;;
- esac
- }
-
- tenspred() { #predecessor of a multiple of ten
- case $1 in
- twenty) echo nineteen;;
- *) echo $(crunchprefix --tens $(pred $(uncrunchprefix ${1%ty})))ty-nine;;
- esac
- }
-
- crunchprefix() {
- #crunch number prefix to its conventional form
- # such as three --> thir
- # option --tens multiples of ten are a bit different
- [ $1 = --tens ] && { tensop=true; shift; }
- case $1 in
- two) [ -n "$tensop" ] && echo twen || echo $1;;
- three) echo thir;;
- four) [ -n "$tensop" ] && echo 'for' || echo $1;;
- five) echo fif;;
- eight) [ -n "$tensop" ] && echo eigh || echo $1;;
- *) echo $1;;
- esac
- }
-
- uncrunchprefix() { #reverse crunchprefix
- case $1 in
- twen) echo two;;
- thir) echo three;;
- 'for') echo four;;
- fif) echo five;;
- eigh) echo eight;;
- *) echo $1;;
- esac
- }
-
- grammar() { #peculiarities of English grammar
- local oneBottle=false #can effect the following line
- while read line; do
- line="${line/one more bottles/one more bottle}"
- case "$line" in
- *"one of those bottles"*) line="$([ $oneBottle = true ] &&
- echo ${line/one of those bottles/that lone bottle} ||
- echo $line )"
- ;;
- *"one down"*) line="$([ $oneBottle = true ] &&
- echo ${line/one down/it down} ||
- echo $line )"
- ;;
- *bottles*) oneBottle=false;;
- *bottle*) oneBottle=true;;
- esac
- #Some say the twenties should have no hyphen
- line="${line/twenty-/twenty }"
- echo $line
- done
- }
-
- capitalize() { #fix beginning of each line
- while read line; do
- echo -n ${line:0:1} | tr '[:lower:]' '[:upper:]'
- echo ${line#?}
- done
- }
-
- punctuate() { #add punct to each line
- while read line; do
- case "${line}" in
- [Ii]f*) echo ${line},;;
- '') echo;;
- *) echo ${line}.;;
- esac
- done
- }
-
- verse () { #write one verse
- local nb=$1
- echo $nb bottles of beer on the wall
- echo $nb bottles of beer
- if [ $nb = zero ]; then
- echo Go to the store and buy some more
- nb=ninety-nine
- else
- echo $breakLine
- nb=$(pred $nb)
- fi
- echo $nb bottles of beer on the wall
- }
-
- poeticize() { #make it nice
- while read first rest; do
- case "$rest" in
- *beer*)
- first=${first/zero/no}
- local syl=$(syllables ${first% *})
- case $syl in #improve meter
- 1|2) echo $first 'more' $rest;;
- *) echo $first $rest;;
- esac
- ;;
- *) echo $first $rest
- esac
- done
- }
-
- syllables() { #estimate number of syls in word
- local n=1
- case $1 in
- eleven) n=2;; #sounds better if not considered 3
- *teen) n=2;;
- *ty) n=2;;
- *-*) n=3;; #don't care about more than 3
- esac
- case $1 in
- *seven*) let $((n = n+1));;
- esac
- echo $n
- }
-
-
- nb=ninety-nine
-
- while [ -n "$nb" ]; do
- verse $nb
- echo
- nb=$(pred $nb)
- done | poeticize | grammar | punctuate | capitalize
|