我想在 PHP 中使用 grep 进行字谜搜索。我有一个包含 600.000 行单个单词(德语单词)的单词列表。
现在我想输入 7 个字母(例如 ABCDEFG),用它们进行所有 5040 种排列(它是 7!),并将每个几乎无意义的字谜可能性(例如 ABCDEFG、ABCDEGF、ABCDGEF,...)输入 grep 中,以检查该单词是否存在在我的列表中。
我在具有 16 GB RAM、PHP 8.0 和 Apache 2.4 的 Ubuntu 22.04 服务器上运行它。
这是将所有 5040 个字谜词添加为模式的最佳方法吗?例如:
shell_exec( 'grep "^ABCDEFG$\|^ABCDEGF$\|..." /path/to/wordlist.txt');
这是好的做法吗?或者使用 for next 循环进行 5040 个 grep 调用并且始终只有一种模式会更好吗?
我读到 grep 可以采用我想要的尽可能多的模式,但我没有找到任何代码,其中有与我的方法一样多的模式。我想最大值受到服务器功能的限制,但我还没有测试过。我不想让服务器速度减慢太多。
或者我的方法根本就不是那么好,最佳实践会完全不同吗?
我尝试使用 sqlite 并使用 sqlite 数据库中的单词列表(每个单词使用 OR ),但这需要太长时间,这是不可能的。
谢谢您的提示。
答案1
由于字谜不关心字母的顺序,因此我们也忽略它可能是有意义的。相反,计算要测试的单词中每个字母的数量,或者更简单的是,对单词的字母进行排序。如果计数或排序后的字符串与键字符串的计数或排序后的版本相匹配,那么您就有了一个字谜词。
可以用 Perl 编写一个简单的单行解决方案。获取以下输入文件:
% cat test.txt
manbat
bantam
hello
然后这应该打印排序后包含“aabmnt”的行:
% perl -lne 'chomp; print if join("", sort split //, $_) eq "aabmnt"' test.txt
manbat
bantam
获取join("", sort split //, $_)
当前行$_
,分隔字符,对它们进行排序,然后再次将它们连接起来。
或者更有用一点,对脚本中的关键字进行排序,这应该给出 的字谜词batman
,要查找的关键字是通过环境传递的:
% key=batman perl -lne 'chomp; print if join("", sort split //, $_) eq join("", sort split //, $ENV{key})' test.txt
manbat
bantam