有没有更有效的方法来使用grep进行拼字游戏搜索?

时间:2015-04-08 23:37:37

标签: regex unix grep command words

我正在解决unix中的以下问题

  1. 假设您正在玩拼字游戏。您的机架中有以下七个字母 - E A F N A S M.这些是您可以用来制作单词的字母,您可以在单词中使用任意数字,但必须至少使用一个。你试图在董事会的一个地方放置一个字,那里已经有一个字:ARE。

    您的目标是找到一个单词,该单词将与您在机架中的字母一起附加到单词ARE。虽然通常你的字母可以放在ARE之前或之后来制作一个新单词,但在这种情况下,ARE位于委员会的边缘,所以你的单词必须以ARE结尾。您的目标是使用grep在/ usr / dict / words中找到符合这些条件的所有可能单词。

  2. 我提出的命令效率很低但有效。

    grep “^[eafnasm][eafnasm]*are$” /usr/dict/words |
    grep -v “a.*a.*a.*a” |
    grep -v “e.*e.*e” |
    grep -v “f.*f” |
    grep -v “n.*n” |
    grep -v “s.*s” |
    grep -v “m.*m” |
    grep -v “^...........”
    

    有更有效的方法吗?

1 个答案:

答案 0 :(得分:2)

加快进度的一种方法是:

grep -E '^[aefmns]{1,7}are$' /usr/dict/words |
grep -Ev 'a.*a.*a.*a|e.*e.*e|f.*f|n.*n|s.*s|m.*m'

它减少了查看数据的进程数量。我从初始字符类中删除了第二个A,因为它是多余的,但重复代表的成本可以忽略不计。在第一个模式中使用{1,7}限定符意味着不需要在第二个模式中过滤超长名称。

请注意,第一次搜索不允许多个R通过。对于这种特殊的手写字母加上字板组合,它是一种专业化。如果手持R(而不是第二个A),则有必要从结果中过滤掉2个以上的R(两个因为在这种情况下,手中有一个R而单词中有一个在板上),多A滤波器也必须改变。

请注意,此处的更改只是对正在运行的原始8 grep命令的轻微调整。由于该解决方案需要使用grep(排除Perl,Python,Awk,...),您可能无法获得少于两个命令,一个'肯定'grep来选择可能性和一个'消极的'grep来消除不可能性。使用自定义工具(用C或C ++或类似程序编写的专用程序),您可能会做得更好。

如果您的grep版本支持PCRE(与Perl兼容的正则表达式),您可以“一体化”。我很确定它的可读性和可理解性较差,虽然它可能表现得更好(因为没有管道,但I / O更少),因此必须测量性能改进。有时,更简单更好。