shell脚本处女作之命令行词典
shell脚本处女作之命令行词典
laichendong 发表于3年前
shell脚本处女作之命令行词典
  • 发表于 3年前
  • 阅读 55
  • 收藏 1
  • 点赞 1
  • 评论 1

腾讯云 十分钟定制你的第一个小程序>>>   

ubuntu下没有一个用着趁手的客户端版词典,查词又作为刚需摆在那里。搜了一下,有人用python和shell写过一些脚本调用web把查词结果显示到命令行,成为“命令行词典”。很有geek范儿。我喜欢“柯林斯词典”的英-英释义,还有例句。现成的那些脚本都没有采纳这个词典。就自己动手,丰衣足食了。作为一个基本上的shell盲来说,这么一个小程序,也很长姿势。 原理很简单。 抓取有道词典相应词语页面的内容。用awk,sed处理截取想要的内容,最后在用自己想要的形式输出出来

一、抓取页面

我使用cur抓取了有道词典的 单词页面
curl -s 'http://dict.youdao.com/search?q='$1''
(-s 参数表示“silence”,安静模式,不会输入多余的信息) 分析页面的源代码发现,如果所查的词有柯林斯词典的解释,将会出现在下面: 20130826195620

二、从源码中截取有用的信息

awk 'BEGIN{j=0;} {if(/collinsToggle/){ j++;} if(j==1) {print $0; if(/<\/ul>/) j=0;}}' | sed 's/<[^>]*>//g' | sed 's/&nbsp;//g'| sed 's/&rarr;//g' | sed 's/^\s*//g' | sed '/^$/d'
这里分了几步来做,首先使用awk找出柯林斯词典的内容,然后用sed移除掉html代码中的标签,空白,空行等等,剩下的就是我们要的“干货“了。关于awk和sed的内容,照着耗子的 AWK简明教程sed简明教程做了几遍,加上一些google就搞定了。感觉awk简直是map-reduce思想的开山鼻祖啊。

三、输出

其实直接就将上面命令的内容输出,功能就已经ok了。勉强也能看。但作为geek又岂能让自己的”第一次“如此丑陋?于是我将命令的输出重定向到一个文件里,然后用read将文件按行读入稍作加工。关于将文件按行读入,也遇到一个小坑。开始我是用的是这个方法读取的文件:
head=''
cat /etc/passwd | while read LINE  
do
        head="$head $LINE"
        echo $LINE 
done
然后发现在循环结束后head并没有改变,然后google到了这篇 帖子,又涨了点姿势。于是我将读取文件的代码稍作了一下修改:
while read line
do
	# do something
done < $TEM_FILE
最后为了美观。想对输出的内容做一点颜色上的调整,突出一下重点。于是又google。发现命令行可用用ANSI颜色来控制文本的样式(用SecureCRT的时候也可以找到这个选项,勾上就有颜色了)。关于ANSI颜色,又 google了一些文章看看就明白了:) 把完整代码贴一下:
#!/bin/bash
ARGS=1
E_BADARGS=65
TEM_FILE="/tmp/dict.tmp"

if [ $# -ne "$ARGS" ]
 then
	echo "Usage:`basename $0` word"
	exit $E_BADARGS
fi

# 抓取页面,删除html代码,空行等,只留下想要的内容
curl -s 'http://dict.youdao.com/search?q='$1'' | awk 'BEGIN{j=0;i=0;} {if(/phrsListTab/){i++;} if(i==1){print $0; if(/<\/ul>/){i=0;}} if(/collinsToggle/){ j++;} if(j==1) {print $0; if(/<\/ul>/){j=0;}}}' | sed 's/<[^>]*>//g' | sed 's/&nbsp;//g'| sed 's/&rarr;//g' | sed 's/^\s*//g' | sed '/^$/d'> $TEM_FILE

# 处理输出
is_head=true # 当前行是否属于“头部”
head="" # 头部内容
body="" # 主体内容
ln_item=0 # 每一条解释的行号
ln_eg=0 # 例句行号

while read line
do
	let ln_item++
	let ln_eg++
	num_flag=`echo "$line" | awk '/[0-9]+\.$/'`
	if [ "$num_flag" != "" ]; then ## 遇见'数字+点'开头的行
		is_head=false # 第一次遇见数字行  将头部标示设置为false
		ln_item=0
	fi

	eg_flag=`echo "$line" | awk '/例:$/'` # 遇见'例:'开头的行
	if [ "$eg_flag" != "" ]; then
		ln_eg=0
	fi

	if $is_head ; then
		head="$head $line"
	else
		if [ $ln_item == 0 ] ; then
			line="\033[32;1m\n\n$line\033[0m" # 释义编号
		elif [ $ln_item == 1 ] ; then
			line="\033[32;1m[$line]\033[0m" # 词性
		elif [ $ln_item == 2 ] ; then
			line="\033[1m$line\033[0m" # 释义 
		elif [ $ln_eg == 0 ] ; then
			line="\033[32;1m\n   $line\033[0m" # 例:
		elif [ $ln_eg == 1 ]; then
			line="\033[33m$line\033[0m" # 例句 
		elif [ $ln_eg == 2 ]; then
			line="\033[33m$line\033[0m" # 例句释义 
		fi
		body="$body $line"
	fi
done < $TEM_FILE
echo -e "\033[31;1m$head\033[0m $body"

exit 0
   
共有 人打赏支持
粉丝 9
博文 85
码字总数 71483
评论 (1)
hehe668
刚开始看到这个源代码,就很喜欢,想知道怎样从页面源代码中如何抓取想要的信息的,反复看了几天,渐渐对整体的框架有了了解.今天又偶遇作者的原创思路,从最初的遇到的问题(ubuntu下没有一个用着趁手的客户端版词典)到提出自己的想法,并根据自己的需求,参考相关的资料,就开始行动了,途中又不断的优化自己的代码.真得干的漂亮.为你点赞.同时感谢你的开源精神!愿大神带菜鸟一起飞!13121213
×
laichendong
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: