玩转 Shell - <emphasis>疯狂填词</emphasis>生成器,第二部分
上个月,我们深入研究了创建疯狂填词生成器——一个您可以提供一段英文散文的程序,然后它会随机选择单词并将其替换为它们的词性,这样您就可以让朋友或家人创作他们自己有趣的替代品。
所以,与其说是“the quick brown fox jumping over that lazy dog”,不如说是“the quick (( adjective )) fox jumps over the (( adjective )) dog”,举个例子。
问题是,从句子中选择随机单词也可能产生更无聊的东西,例如“(( definite article )) quick brown fox jumps over (( definite article)) lazy dog”。
本月,我将采用那个随机单词选择工具,并添加一些智能,使其偏向于更长的单词和名词或形容词。
上个月,您应该还记得我们的脚本有一个单词选择代码段,如下所示
while read sentence ; do for word in $sentence ; do if [ $(( $RANDOM % $density )) -eq 1 ] ; then echo "(($word))" else echo $word fi done
我们需要扩展代码的地方是在当前仅将单词放在括号中的条件内。 第一步是分析长度:如果单词的长度小于或等于三个字母,我们将不太可能选择它
if [ $(( $RANDOM % $density )) -eq 1 ] ; then length=$(/bin/echo -n $word | wc -c | sed 's/ //g') if [ $length -lt 4 -a $(( $RANDOM % 2 )) -eq 1 ] ; then echo \{$word\} # too short else echo "(($word))" fi else
这效果很好——实际上,每次选择一个单词时,都会检查它的长度。 长度小于四个字母的单词有 50% 的几率被忽略。 有了一个简单的输入示例,这就是我们得到的结果
{the} ((quick)) brown fox jumped ((over)) the lazy black dog
仍然不是很好,但至少它意识到“the”由于长度而没有意义。 我仍然对它选择替换哪些单词不太满意,但让我们继续这个项目的第二部分,测试词性,然后再回到选择标准。
这部分的核心代码已经在上个月介绍过了,它利用了普林斯顿大学的实用 WordNet,所以这里是它
pos="$(curl --silent "$dictionary$word" | grep '<h3>' | head -1 \ | tr '[:upper:]' '[:lower:]' | sed 's/<h3>//;s/<\/h3>//')" if [ ! -z "$(echo $pos | grep "not return any results")" ] ; then echo \[$word\] # failed to figure out part of speech else echo "((${word}:$pos))" fi
请注意,我们必须担心查找失败。 有些单词在 WordNet 词典中找不到,我们需要做好准备。 我将它们按照编写方式联系起来,这是我们得到的输出
Note: {} = too short, [] = POS undefined ((I:noun)) {am} {by} ((birth:noun)) {a} Genovese, and {my} family {is} one of the most ((distinguished:verb)) of that ((republic:noun))
正如标题提醒我们的那样,此时,我们用 {} 表示选择但跳过的单词,因为它们太短了,用 [] 表示那些词性未定义的单词。
我还更改了单词替换密度因子,以便测试更多单词。 正如您所看到的,现在我们示例输入中的大多数单词都以某种方式进行了评估。
现在,让我们添加一个测试,以便只有名词或形容词才有资格被替换
if [ ! -z "$(echo $pos | grep "not return")" ] ; then echo \[$word\] # failed to figure POS else if [ -n "$(echo $pos | grep -E '(noun|adjective)')" ] ; then echo "((${word}:$pos))" else echo "<${word}:$pos>" fi fi
我会把同样的第一个句子给玛丽·雪莱的弗兰肯斯坦,让我们看看会发生什么
Note: {} = too short, [] = POS undefined, <> = uninteresting POS I {am} <by:adverb> birth {a} Genovese, [and] my family ((is:noun)) {one} {of} {the} ((most:adjective)) <distinguished:verb> {of} [that] ((republic:noun))
我们肯定正在接近目标,但我认为我们仍然需要添加一些到选择标准中——一些可以帮助我们产生更有趣的疯狂填词的东西。
但是,让我们留到下个月吧,因为在本专栏中我们已经研究了很多代码。
Dave Taylor 编写 shell 脚本已经有很长时间了,30 年。 他是广受欢迎的Wicked Cool Shell Scripts的作者,可以在 Twitter 上找到他,账号为@DaveTaylor,更常见的是在www.DaveTaylorOnline.com。