玩转 Shell - 电影知识问答 — 终于来了!
这就像谚语所说的一样,经历了成千上万步的旅程,但我认为在花费了过去几个月进行所有底层工具开发之后,我们终于准备好开始生成一些电影知识问答了。您可能还记得,我们正在从亚马逊的 IMDb 网站抓取前 250 名电影列表,然后获取每部电影的发行年份并将其存储在数据库中。
另外,我们还研究了一个有趣的问题,即为给定的年份提出相邻年份,认识到电影越老,我们想要的年份差距就越大,因为很少有人会错误地猜测 2007 年发行的电影是在 1983 年发行的,但 1947 年发行的电影可能会让人们认为它是 1931 年发行的。
现在,是时候将各个部分组合在一起了。
上一栏深入研究了年份范围,最终得到了一个脚本,该脚本为给定年份生成了一个可能的相邻年份。我们需要改进这个脚本,因为我们想要生成三个不同的年份可能性,其中两个是可能但错误的年份,一个是正确的年份,没有重复。
首先,让我们将生成合理的相邻年份的代码创建一个脚本函数
get_random() { delta="$(( $RANDOM % $factor + 1))" add="$(( $RANDOM % 2 ))" if [ $add -eq 1 ] ; then closeyear="$(( $releasedate + $delta ))" else closeyear="$(( $releasedate - $delta ))" fi if [ $closeyear -gt $thisyear ] ; then closeyear="$(( $releasedate - $delta ))" fi }
接下来,考虑到我们无法在不使用全局变量的情况下优雅地返回值,以下是我们如何利用该函数
get_random match1=$closeyear
这很容易让我们得到第一个年份猜测。但是,下一个猜测需要与第一个不同。如何做到这一点? 在 while 循环中
match2=$match1 # needs an initial value while [ $match2 -eq $match1 ] ; do get_random match2=$closeyear done
这有点冒险,因为如果代码永远找不到不同的随机年份值,则存在无限循环的可能性,但我现在将忽略它。
现在我们有三个年份值:两个不正确的年份, $match1 和 $match2,以及正确的值, $releasedate。 如何将它们排序后返回给调用例程? 简单
echo "$match1 $match2 $releasedate" | sort -n
这就是函数。 给它一个年份,它会返回三个:两个接近但错误的年份,和一个正确的年份。 例如
$ ./year-delta.sh 1975 1981 1971 1975 $ ./year-delta.sh 1999 2000 1998 1999 $ ./year-delta.sh 1938 1948 1935 1938
这正是我们想要的。 现在,如何将其集成到更大的脚本中,该脚本从 IMDb 数据库中抓取随机行,然后以可用的方式呈现它?
一旦你记住了这个技巧$(( $RANDOM % some-value)),从数据文件中获取随机行应该很简单
lines="$(wc -l < $filmdb | sed 's/ //g')" randline=$(( $RANDOM % $lines + 1 )) match="$(sed -n "${randline}p" < $filmdb)"
正如我之前写过的, wc 是您在脚本编写中最好的朋友之一,因为它很简单。 但是,令人沮丧的是,没有办法关闭它生成的多余的空格。 这就是为什么第一行包含对 sed 的调用以删除添加的任何空格的原因。 在我们自己的平行宇宙中,有一个 -n 标志可以告诉 wc “没有填充”,这使它永远不必要。 可悲的是,我们不在那个宇宙中,所以几乎每次你使用 wc 时,你都必须同时删除空格。
这三行的结果是 match 具有类似于以下的值
The Lord of the Rings: The Two Towers|2002
现在我们需要将它分成两个字段,这很容易,即使很繁琐
title="$(echo $match | cut -d\| -f1)" relyear="$(echo $match | cut -d\| -f2)"
最后,是时候调用随机年份函数了,如果您还记得,它将生成一个正确年份和两个不正确年份
years=$($randomyears $relyear)
最后,让我们将这三年份提取到单独的变量中,然后输出一个有吸引力的知识问答查询
year1="$(echo $years | cut -d\ -f1)" year2="$(echo $years | cut -d\ -f2)" year3="$(echo $years | cut -d\ -f3)" echo "IMDb Top 250 Movie #$randline: Was $title released in $year1, $year2 or $year3?"
不太寒酸! 让我们看看它是如何工作的
$ ./generate-trivia-question.sh IMDb Top 250 Movie #82: Was "Some Like It Hot" released in 1950, 1959 or 1963? $ ./generate-trivia-question.sh IMDb Top 250 Movie #118: Was "Mononoke-hime" released in 1994, 1995 or 1997? $ ./generate-trivia-question.sh IMDb Top 250 Movie #250: Was "Planet of the Apes" released in 1967, 1968 or 1969?
完美,完美!
这就是我们本专栏的所有内容了,但我们已经从一个列出一些热门电影的网页的 URL 发展到快速而有趣的小型知识问答引擎,这已经走了很长很长的路!
下个月,我们将研究如何将知识问答注入到 Twitter 流中。 想看看它的实际效果吗? 当您阅读本专栏时,它将在 twitter.com/FilmBuzz 上线(以及电影评论等等)。
Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,The Elm Mail System 的创建者,以及最近畅销书 Wicked Cool Shell Scripts 和 Teach Yourself Unix in 24 Hours 的作者,他的 16 本技术书籍。 他的主要网站是 www.intuitive.com,他还提供技术支持:AskDaveTaylor.com。 如果您愿意,可以在 Twitter 上关注他:twitter.com/DaveTaylor。