玩转 Shell - 电影知识问答 — 终于来了!

作者:Dave Taylor

这就像谚语所说的一样,经历了成千上万步的旅程,但我认为在花费了过去几个月进行所有底层工具开发之后,我们终于准备好开始生成一些电影知识问答了。您可能还记得,我们正在从亚马逊的 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 ScriptsTeach Yourself Unix in 24 Hours 的作者,他的 16 本技术书籍。 他的主要网站是 www.intuitive.com,他还提供技术支持:AskDaveTaylor.com。 如果您愿意,可以在 Twitter 上关注他:twitter.com/DaveTaylor

加载 Disqus 评论