【问题标题】:Why does this PHP spintax code repeat identical iterations?为什么这个 PHP spintax 代码重复相同的迭代?
【发布时间】:2012-08-03 22:24:55
【问题描述】:

http://ronaldarichardson.com/2011/09/23/recursive-php-spintax-class-3-0/

我喜欢这个脚本,但它并不完美。如果你使用这个测试输入用例:

{这是我的 {spintax|spuntext} 格式化字符串,我的 {spintax|spuntext} 格式化字符串,我的 {spintax|spuntext} 格式化字符串示例。}

您可以看到结果总是包含 3 次重复的“spintax”或“spuntext”。例如,它从不包含 1 个“spintax”和 2 个“spuntext”。

例子:

这是我的 spuntext 格式化字符串、我的 spuntext 格式化字符串、我的 spuntext 格式化字符串示例。

要真正随机,它需要为每个 spintax {|} 块生成随机迭代,而不是为相同的块重复相同的选择,例如 {spintax|spuntext}。

如果您查看该页面上的评论 #7,fransberns 是在做某事,但是当在实时环境中使用他修改过的代码时,该脚本会在无限循环中反复运行并耗尽所有服务器内存。所以那里一定有一个bug,但我不确定它是什么。

有什么想法吗?或者有谁知道一个健壮的 PHP spintax 脚本,它允许嵌套 spintax 并且是真正随机的?

【问题讨论】:

  • 旁注:你真的希望它是随机的吗?还是您正在寻找不同的输出?如果它是随机的,完全有可能有很多重复的单词。
  • 我现在没有机会编写和测试它,但是您需要对 preg_replace 应用限制,并在目标单词仍在文档中时循环。添加一个计数器并在 20 个循环之后中断,以避免无限循环。
  • @HappyTimeGopher - 是的,随机的。我很好,在上述情况下,“spintax”偶尔重复 3 次,而不是每次运行该函数时;)

标签: php spintax


【解决方案1】:

请检查这个gist,它正在工作(它比原始代码简单得多..)。

【讨论】:

  • 这是我最终采用的解决方案,因为它比我使用的原始代码更优雅。
【解决方案2】:

Spintax 类用随机选择的相同选项替换 {spintax|spuntext} 的 所有 个实例的原因是因为类中的这一行:

  $str = str_replace($match[0], $new_str, $str);

str_replace 函数将子字符串的 all 实例替换为搜索字符串中的替换。要仅替换第一个实例,按照您的需要以串行方式进行,我们需要使用函数preg_replace,传递的“count”参数为1。但是,当我查看@987654321 @ 到 Spintax 类并参考帖子 #7 我注意到他建议的对 Spintax 类的扩充中有一个错误。

fransberns 建议替换:

$str = str_replace($match[0], $new_str, $str);

用这个:

//one match at a time
$match_0 = str_replace("|", "\|", $match[0]);
$match_0 = str_replace("{", "\{", $match_0);
$match_0 = str_replace("}", "\}", $match_0);
$reg_exp = "/".$match_0."/";
$str = preg_replace($reg_exp, $new_str, $str, 1);

fransbergs' 建议的问题在于,在他的代码中,他没有为preg_replace 函数正确构造正则表达式。他的错误来自没有正确转义\ 字符。他的替换代码应该是这样的:

//one match at a time
$match_0 = str_replace("|", "\\|", $match[0]);
$match_0 = str_replace("{", "\\{", $match_0);
$match_0 = str_replace("}", "\\}", $match_0);
$reg_exp = "/".$match_0."/";
$str = preg_replace($reg_exp, $new_str, $str, 1);

考虑利用我对fransberns'建议的replacemnet的更正,用这个增强版本替换原来的类:

class Spintax {

   function spin($str, $test=false)
   {
      if(!$test){
         do {
            $str = $this->regex($str);
         } while ($this->complete($str));
         return $str;
      } else {
         do {
            echo "<b>PROCESS: </b>";var_dump($str = $this->regex($str));echo "<br><br>";
         } while ($this->complete($str));
         return false;
      }
   }

   function regex($str)
   {
      preg_match("/{[^{}]+?}/", $str, $match);
      // Now spin the first captured string
      $attack = explode("|", $match[0]);
      $new_str = preg_replace("/[{}]/", "", $attack[rand(0,(count($attack)-1))]);
//      $str = str_replace($match[0], $new_str, $str); //this line was replaced
      $match_0 = str_replace("|", "\\|", $match[0]);
      $match_0 = str_replace("{", "\\{", $match_0);
      $match_0 = str_replace("}", "\\}", $match_0);
      $reg_exp = "/".$match_0."/";
      $str = preg_replace($reg_exp, $new_str, $str, 1);    
      return $str;
   }

   function complete($str)
   {
      $complete = preg_match("/{[^{}]+?}/", $str, $match);
      return $complete;
   }
}

当我尝试使用 fransberns' 建议的替换“原样”时,由于 \ 字符的不正确转义,我得到了一个无限循环。我认为这就是您的记忆问题的根源。在更正fransberns' 建议替换为\ 字符的正确转义后,我没有进入无限循环。

用更正的增强试试上面的类,看看它是否在你的服务器上工作(我看不出它不应该的原因)。

【讨论】:

    猜你喜欢
    • 2011-05-07
    • 1970-01-01
    • 2015-03-26
    • 2011-08-22
    • 2021-01-24
    • 1970-01-01
    • 2010-10-20
    • 2016-11-29
    • 1970-01-01
    相关资源
    最近更新 更多