深度(无限)嵌套使用正则表达式拆分单词


Deep (infinite) NESTED split words using regex

重要编辑:由于许多人说应该避免这种情况,而且几乎无法使用RegEx,我将允许您提供一些其他解决方案。从现在起,任何解决方案都可以作为答案,最终成为解决方案。谢谢

假设我有:

$line = "{ It is { raining { and streets are wet } | snowing { and streets are { slippy | white }}}. Tomorrow will be nice { weather | walk }. }" 

期望输出:

It is raining and streets are wet. Tomorrow will be nice weather.
It is raining and streets are wet. Tomorrow will be nice walk.
It is snowing and streets are slippy. Tomorrow will be nice weather.
It is snowing and streets are slippy. Tomorrow will be nice walk.
It is snowing and streets are white. Tomorrow will be nice weather.
It is snowing and streets are white. Tomorrow will be nice walk. 

使用这个答案中的代码来回答我之前的问题,我目前可以拆分单词,但无法计算嵌套的值。有人能帮我解决我的问题吗。我很确定我应该在某个地方实现for循环以使其工作,但我不明白在哪里。

$line = "{This is my {sentence|statement} I {wrote|typed} on a {hot|cold} {day|night}.}";
 $matches = getMatches($line);
 printWords([], $matches, $line);

function getMatches(&$line) {
    $line = trim($line, '{}'); 
    $matches = null;
    $pattern = '/'{[^}]+'}/';
    preg_match_all($pattern, $line, $matches);
    $matches = $matches[0];
    $line = preg_replace($pattern, '%s', $line);
    foreach ($matches as $index => $match) {
        $matches[$index] = explode('|', trim($match, '{}'));
    }
    return $matches;
}

function printWords(array $args, array $matches, $line) {
    $current = array_shift($matches);
    $currentArgIndex = count($args);
    foreach ($current as $word) {
        $args[$currentArgIndex] = $word;
        if (!empty($matches)) {
                printWords($args, $matches, $line);
        } else {
                echo vsprintf($line, $args) . '<br />';
        }
    }
}

我想到的一种方法是使用lexer技术,就像逐字符读取一样,创建适当的字节码,然后循环通过它。这不是regex,但它应该可以工作。

这个类完成工作,尽管不确定它的效率有多高:

class Randomizer {
    public function process($text) {
        return preg_replace_callback('/'{(((?>[^'{'}]+)|(?R))*)'}/x', array($this, 'replace'), $text);
    }
    public function replace($text) {
        $text = $this->process($text[1]);
        $parts = explode('|', $text);
        $part = $parts[array_rand($parts)];
        return $part;
    }
}

要使用它,你可以简单地做:

$line = "{This is my {sentence|statement} I {wrote|typed} on a {hot|cold} {day|night}.}";
$randomizer = new Randomizer( );
echo   $randomizer->process($line);

在正则表达式方面,我不是最好的,所以我无法真正解释为什么那个特定的正则表达式有效,很抱歉。

顺便说一下,它返回随机字符串,而不是所有可能的字符串。如果你需要所有的字符串而不是随机的字符串,请告诉我。我将更新答案。。