Skip to content

Instantly share code, notes, and snippets.

@geekontheway
Created November 27, 2011 14:40
Show Gist options
  • Save geekontheway/1397639 to your computer and use it in GitHub Desktop.
Save geekontheway/1397639 to your computer and use it in GitHub Desktop.
回顾 Shell
```shell
#101 A State Capitals Quiz
#Once you have a tool for choosing a line randomly from a file, as we have with Script #76, Displaying Random Text, there's no limit to the type of quiz games you can write. In this instance, I've pulled #together a list of the capitals of all 50 states in the United States of America; this script randomly chooses one, shows the state, and asks the user to type in the matching capital.
#The Code
#!/bin/sh
# states - A state capital guessing game. Requires the state capitals
# data file at http://www.intuitive.com/wicked/examples/state.capitals.txt.
db="/usr/lib/games/state.capitals.txt"
randomquote="$HOME/bin/randomquote.sh" # Script #76
if [ ! -r $db ] ; then #可读
echo "$0: Can't open $db for reading." >&2
echo "(get http://www.intuitive.com/wicked/examples/state.capitals.txt" >&2
echo "save the file as $db and you're ready to play!)" >&2 #创建该路径
exit 1
fi
guesses=0; correct=0; total=0
while [ "$guess" != "quit" ] ; do
thiskey="$($randomquote$db)"
state="$(echo $thiskey | cut -d\ -f1 | sed 's/-/ /g')" # -d制定分隔符-f 列 -c行 本行中分隔符为空格?
city="$(echo $thiskey | cut -d\ -f2 | sed 's/-/ /g')"
match="$(echo $city | tr '[:upper:]' '[:lower:]')" # match="$(echo $city | tr '[A-Z]' '[a-z]')"
guess="??" ; total=$(( $total + 1 )) ;
echo ""
echo "What city is the capital of $state?"
while [ "$guess" != "$match" -a "$guess" != "next" -a "$guess" != "quit" ]
do
echo -n "Answer: "
read guess
if [ "$guess" = "$match" -o "$guess" = "$city" ] ; then
echo ""
echo "*** Absolutely correct! Well done! ***"
correct=$(( $correct + 1 ))
guess=$match
elif [ "$guess" = "next" -o "$guess" = "quit" ] ; then
echo ""
echo "$city is the capital of $state."
else
echo "I'm afraid that's not correct."
fi
done
done
echo "You got $correct out of $total presented."
exit 0
#How It Works
#For such an entertaining game, states is very simple scripting. The data file contains state/capital pairs, with all spaces in the state and capital names replaced with dashes and the two fields separated by a single space. As a result, extracting the city and state names from the data is easy:
#state="$(echo $thiskey | cut -d\ -f1 | sed 's/-/ /g')"
#city="$(echo $thiskey | cut -d\ -f2 | sed 's/-/ /g')"
#Each guess is compared against both the all-lowercase version of the city name (match) and the actual correctly capitalized city name to see if it's correct. If not, the guess is compared against the two command words next and quit. If either matches, the script shows the answer and either prompts for another state or quits, as appropriate.
#Running the Script
#This script has no arguments or command flags.
#The Results
#Ready to quiz yourself on state capitals?
#$ states
#What city is the capital of Indiana?
#Answer: Bloomington
#I'm afraid that's not correct.
#Answer: Indianapolis
#*** Absolutely correct! Well done! ***
#What city is the capital of Massachusetts?
#Answer: Boston
#*** Absolutely correct! Well done! ***
#Fortunately, the game tracks only ultimately correct guesses, not how many incorrect guesses you made or whether you popped over to Google to get the correct answer! :-)
#Hacking the Script
#Probably the greatest weakness in this game is that it's so picky about spelling. A useful modification would be to add some code to allow fuzzy matching, so that the user entry of Juneu might match Juneau, for example. This could be done using a modified Soundex algorithm, in which all vowels are removed and all doubled letters are squished down to a single letter (e.g., Annapolis would transform to npls). This might be too forgiving for your tastes, but the general concept is worth considering.
#As with other games, a "hint" function would be useful too. Perhaps it would show the first letter of the correct answer when requested but keep track of how many hints were used as the play proceeded.
#Although this game is written around state capitals, it would be quite trivial to modify the script to work with any sort of paired data file. For example, you could create an Italian vocabulary quiz with a slightly different file, or a country/ currency match, or even a politician/political party quiz. Again, as we've seen repeatedly in Unix, writing something that is reasonably general purpose allows it to be reused in useful and occasionally unexpected ways.
```
```shell
grep 'jion' etc/password
echo $status
echo $?
grep nw d*
grep '4$' data
grep 'tb sabbge' data #doule or single works
grep '5\...' data
grep '^[we]' data
grep 'ss*' data
egrep 's+' data
grep '\<north' data
grep '^north' data
grep '\<north\>'data
grep '\bnorth\b' data
grep '^n\w*\W' data #w字母数字
grep '\b[a-z].*n\b' data #n前面有任意多个字符
egrep 'nw|fa' data
grep 'nw\|fa' data
egrep '2\.?[0-9]' data
egrep '(no)+' data
egrep 's(n|o)+' data
egrep '(no)+' data
egrep 'w(es)t.*\1' data #如果找到west标记es 则保存到寄存器1
egrep '\.[0-9]{3}[^0-9]' data
#固定grep-F
#递归 rgrep
#选项
-b 修改每一行的字符偏移
-c 匹配的行数量
-e 平等对待
-f 模板
-h 不显示文件名
-i 忽略大小写
-l 文件名清单
-n 行号
-s 静默
-v 反检索
-w 单词
-x 整行
#例子
grep -i "$LOGNAME" data
grep --regexp=-47 data
grep -x -e '-167 is cold' data
grep -f pattern data
grep -h '[0-9]' data1 data2
grep --quite chaelws data
```
```shell
sed -n '/marth/p ' data #Print lines match 'marth' quietly
sed '1,3d' data1>data2
sed '/[Dd]aniel/d' data
sed '1,10s/noeth/east/g' data
sed '/marth/!d' data #sh
sed '/narth/s/5/8' data #only functioned in line1 that matched
sed 's/....//' data #Delete the first four words every line
sed 's/...$//' data #Delete the last three words every line
sed '/west/,/north/s/man/woman/'
sed -n '/time off/w timefile' data # write into timefile
sed '/susan/r newfile' data #write into data after line./susan/
sed -n '/^nor/a\\
sed '5q' data #quit after print line5
sed '1,3y/abcedfghijklmnopqrstuvwxyz/ABCDEFG
HIJKLMNOPQRSTUVWXYZ/' data # change style Need a '\'after 'G' ?
sed -e '/^nor/h' -e '/^sou/x' data #Exchange
sed -e '/north/h' -e '$g' data #Cover
sed -e '/north/h' -e '$G' data #Append
sed -e '/north/{h;d; }' -e '$G' data #Shift and Append
```shell
```shell
#参数传递
$*
$#
shift #左移位置参数,$1 第一个无可挽回的损失
shift 3 #左移三个位置
${n} # 类似¥{12}
grep susan book; grep "susan t" book; #在book中查找
grep "$1" book #脚本中的方法
> echo “$1 $2”>> book #双引号防止两个参数之间的Tab被翻译;用于添加项
> sort -o book book #添加项后文件次序应保持不变
> grep -v “$1”book > /tmp/book \
mv /tmp/book book #设计一个删除指定姓名或者号码的行
> egrep -v “($1|$2)”book > /tmp/book \
mv /tmp/book book
>sed "/$1/d" book > /tmp/book \
mv /tmp/book book #也可以实现删除
>sed “/$1/”{s/$2/$3/;} #编辑选项
#去掉文件名后缀:cutit love.mp3 .mp3
sed -e“/$1/h”-e "/$2/x"
#给出一个用户,显示其工作目录 pwd
>grep "$1" etc/password | cut -f6
```
#24 An Interactive Calculator
#Once I wrote Script #9, allowing command-line invocations of bc for floatingpoint calculations, it was inevitable that I'd write a small wrapper script to create an interactive command-line-based calculator. What's remarkable is that, even with help information, it's very short.
#The Code
```
#!/bin/sh
# calc - A command-line calculator that acts as a front end to bc.
scale=2
show_help()
{
cat << EOF
In addition to standard math functions, calc also supports
a % b remainder of a/b
a ^ b exponential: a raised to the b power
s(x) sine of x, x in radians
c(x) cosine of x, x in radians
a(x) arctangent of x, returns radians
l(x) natural log of x
e(x) exponential log of raising e to the x
j(n,x) bessel function of integer order n of x
scale N show N fractional digits (default = 2)
EOF
}
if [ $# -gt 0 ] ; then
exec scriptbc "$@"
fi
echo "Calc - a simple calculator. Enter 'help' for help, 'quit' to quit."
echo -n "calc> "
while read command args
do
case $command
in
quit|exit) exit 0 ;;
help|\?) show_help ;;
scale) scale=$args ;;
*) scriptbc -p $scale "$command" "$args" ;;
esac
echo -n "calc> "
done
echo ""
exit 0
#How It Works
#There's really remarkably little of a complex nature going on here. Perhaps the most interesting part of the code is the while read statement, which creates an infinite loop that displays the calc> prompt until the user exits, either by typing quit or entering an end-of-file sequence (^D). And, of course, the simplicity of this script is exactly what makes it wonderful: Shell scripts don't need to be extremely complex to be useful!
#Running the Script
#This script is easily run because by default it's an interactive tool that prompts the user for the desired actions. If it is invoked with arguments, those arguments are passed to the scriptbc command instead.
#The Results
#$ calc 150 / 3.5
#42.85
#$ calc
#Calc - a simple calculator. Enter 'help' for help, 'quit' to quit.
#calc> help
#In addition to standard math functions, calc also supports
#a % b remainder of a/b
# a ^ b exponential: a raised to the b power
# s(x) sine of x, x in radians
#c(x) cosine of x, x in radians
# a(x) arctangent of x, returns radians
# l(x) natural log of x
#e(x) exponential log of raising e to the x
# j(n,x) bessel function of integer order n of x
# scale N show N fractional digits (default = 2)
#calc> 54354 ^ 3
#160581137553864
#calc> quit
#$
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment