第三章:Creating Utilities--26.Shpell: 一个交互式的拼写检查工具
本脚本用来检查、修复拼写错误。上一个脚本时只能对单个单词检查、修复,而这个脚本的操作对象是一个文件,并且和用户是交互式进行的。
代码:
1 #!/bin/sh 2 3 # shpell.sh -- 一个交互式的拼写检查程序 4 # 该程序允许你单步调试文档中所有已知的拼写错误 5 # 原始版本的文件会被另存为一个.shp后缀的文件 6 # 新版本文件会则会替换旧的 7 # 8 # 注意: 你需要一个标准的'spell'命令来完成这些工作, 9 # 这些命令在你的系统上可能是以下之一: aspell, ispell, pspell 10 11 tempfile="/tmp/$0.$$" 12 changerequests="/tmp/$0.$$.sed" 13 spell="ispell -l" # 根据自己需要的sepll修改 14 15 trap "rm -f $tempfile $changerequests" EXIT HUP INT QUIT TERM 16 17 # 原文中引入了ansi的颜色序列,由于老七的终端不支持,在此省略掉了 18 19 getfix() 20 { 21 22 # 要求用户指定一个修正项。如果用户输入的替换单词仍然有拼写错误, 23 # 这个函数就会调用自己,形成一个2层嵌套 24 # 这个可以按照用户需要达到多层嵌套,但是追踪嵌套轨迹可以让我 25 # 们确保只有第一层嵌套会输出"替换单词"信息. 26 27 word=$1 28 filename=$2 29 misspelled=1 30 31 while [ $misspelled -eq 1 ] 32 do 33 echo "" 34 echo "Misspelled word ${word}" 35 grep -n $word $filename | 36 sed -e 's/^/ /' -e "s/$word/\"$word\"/g" 37 # 原书中,这儿的替换项是带有色彩的, 而此处,我则用引号代替下 38 echo -n "i)gnore, q)uit, or type replacement: " 39 read fix 40 if [ "$fix" = "q" -o "$fix" = "quit" ]; then 41 echo "Exiting without applying an fixes." 42 exit 0 43 elif [ "${fix%${fix#?}}" = "!" ]; then 44 misspelled=0 # 用户强制替换,停止检查 45 echo "s/$word/${fix#?}/g" >>$changerequests 46 elif [ "$fix" = "i" -o -z "$fix" ]; then 47 misspelled=0 48 else 49 if [ ! -z "$(echo $fix | sed 's/[^ ]//g')" ]; then 50 misspelled=0 # 一遇到空白,停止检测 51 echo "s/$word/$fix/g" >> $changerequests 52 else 53 # 它是一个单词的替换项,也要检查它的拼写 54 if [ ! -z "$(echo $fix | $spell)" ]; then 55 echo "" 56 echo "*** Your suggested replacement $fix is misspelled." 57 echo "*** Preface the word with '!' to force acceptance." 58 else 59 misspelled=0 # 建议的替换项符合条件 60 echo "s/$word/$fix/g" >> $changerequests 61 fi 62 fi 63 fi 64 done 65 } 66 67 if [ $# -lt 1 ]; then 68 echo "Usage: $0 filename" >&2 69 exit 1 70 fi 71 72 if [ ! -r $1 ]; then 73 echo "$0: Cannot read file $1 to check spelling" >&2 74 exit 1 75 fi 76 77 errors="$($spell < $1 | tee $tempfile | wc -l | sed 's/[^[:digit:]]//g')" 78 79 if [ $errors -eq 0 ]; then 80 echo "There are no spelling errors in $1." 81 exit 0 82 fi 83 84 echo "We need to fix $errors misspellings in the document. Remember that the" 85 echo "default answer to the spelling prompt is 'ignore', if you're lazy." 86 87 touch $changerequests 88 89 for word in $(cat $tempfile) 90 do 91 getfix $word $1 1 92 done 93 94 if [ $(wc -l < $changerequests) -gt 0 ]; then 95 sed -f $changerequests $1 > $1.new 96 mv $1 $1.shp 97 mv $1.new $1 98 echo Done. Made $(wc -l < $changerequests) changes. 99 fi 100 101 exit 0
脚本如何工作:
脚本中最重要的就是getfix函数。如果有错时它会提示用户,是替换掉,还是忽略掉这个拼写错。如果你选择替换掉,那么这个函数也会检查你提供的替换项的拼写,如果脚本仍然认为这个单词拼写错误,那么你可以在单词的头部加上一个惊叹号来强制脚本接受这个替换项。
文本替换是由一个sed脚本完成的,它叫$changerequests,在用户完成检视完所有的错误后,脚本调用这个sed脚本进行替换。
还有一个值得一提的是脚本开头的trap命令,它确保所有的临时文件都会被删除。如果你仔细看了脚本的结尾处,你会发现原始文件变成了一个.shp后缀的文件,它是为了防止发生某些错误。预判可能的问题始终是一项聪明的策略,特别是对于修改输入文件的那些脚本。
运行脚本:
只要给这个脚本一个文件名作为参数就行了
运行结果:
View Code
$ shpell ragged.txt We need to fix 5 misspellings in the document. Remember that the default answer to the spelling prompt is 'ignore', if you're lazy. Misspelled word herrself: 1:So she sat on, with closed eyes, and half believed herrself in i)gnore, q)uit, or type replacement: herself Misspelled word reippling: 3:all would change to dull reality--the grass would be only rustling in the wind, and the pool reippling to the waving of the reeds--the i)gnore, q)uit, or type replacement: rippling Misspelled word teacups: 4:rattling teacups would change to tinkling sheep-bells, and the i)gnore, q)uit, or type replacement: Misspelled word Gryphon: 7:of the baby, the shriek of the Gryphon, and all the other queer noises, would change (she knew) i)gnore, q)uit, or type replacement: Misspelled word clamour: 8:to the confused clamour of the busy farm-yard--while the lowing of i)gnore, q)uit, or type replacement: Done. Made 2 changes. It's impossible to reproduce here in the book, but the ANSI color sequences let the misspelled words stand out in the output display.
注: 以上的运行结果直接摘抄自原文。因为在老七的机器上ispell -l 是检查不出来单词的拼写错误的。原因也没搞清楚。大家可以在自己的Linux上试试看,有结果反馈给老七。另外,大家知道怎么修改代码的字体吗,这个courier new的字体个人不大喜欢,想换成consolas的,大家有什么好办法吗?谢啦。