PHP Spintax处理器

时间:2012-11-20 18:26:16

标签: php regex string spintax

我一直在使用recurisve SpinTax处理器,如here所示,它适用于较小的字符串。但是,当字符串超过20KB时,它开始耗尽内存,这就成了一个问题。

如果我有这样的字符串:

{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!

我希望将这些单词的随机组合放在一起,使用上面链接中所见的技术(通过字符串递归,直到花括号中没有更多的单词) ,我该怎么办?

我在考虑这样的事情:

$array = explode(' ', $string);
foreach ($array as $k=>$v) {
        if ($v[0] == '{') {
                $n_array = explode('|', $v);
                $array[$k] = str_replace(array('{', '}'), '', $n_array[array_rand($n_array)]);
        }
}
echo implode(' ', $array);

但是当spintax的选项之间存在空格时它会崩溃。 RegEx似乎是解决方案,但我不知道如何实现它具有更高效的性能。

谢谢!

3 个答案:

答案 0 :(得分:5)

您可以创建一个使用回调函数的函数来确定将创建和返回多个潜在的变体:

// Pass in the string you'd for which you'd like a random output
function random ($str) {
    // Returns random values found between { this | and }
    return preg_replace_callback("/{(.*?)}/", function ($match) {
        // Splits 'foo|bar' strings into an array
        $words = explode("|", $match[1]);
        // Grabs a random array entry and returns it
        return $words[array_rand($words)];
    // The input string, which you provide when calling this func
    }, $str);
}

random("{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!");
random("{This|That} is so {awesome|crazy|stupid}!");
random("{StackOverflow|StackExchange} solves all of my {problems|issues}.");

答案 1 :(得分:3)

您可以使用preg_replace_callback()指定替换功能。

$str = "{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!";

$replacement = function ($matches) {
    $array = explode("|", $matches[1]);
    return $array[array_rand($array)];
};

$str = preg_replace_callback("/\{([^}]+)\}/", $replacement, $str);
var_dump($str);

答案 2 :(得分:0)

适用于{a|b{c|d{e|f}|}}

的递归解决方案
/**
 * Method used for spintax string processing
 * @param $text {a|b{c|d}}
 * @return string a or bc or bd
 */
function spintax($text): string
{
    return preg_replace_callback(
        '/\{(((?>[^\{\}]+)|(?R))*)\}/x',
        static
        function ($text) {
            $text = self::spintax($text[1]);
            $parts = explode('|', $text);
            return $parts[array_rand($parts)];
        },
        $text
    );
}