【问题标题】:Deep (infinite) NESTED split words using regex使用正则表达式的深度(无限)嵌套拆分词
【发布时间】:2016-07-24 14:53:18
【问题描述】:

重要编辑: 由于许多人说应该避免这种情况,并且几乎无法使用 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. 

使用this answer 到我上一个问题的代码,我目前能够拆分单词但无法找出嵌套值。有人可以帮我解决我下面的问题。我很确定我应该在某处实现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 技术,如逐字符读取,创建适当的字节码,然后循环遍历它。这不是正则表达式,但它应该可以工作。

【问题讨论】:

  • 您想要的输出是您发布的上述输出还是您当前生产的输出?
  • 上面的输出是我想要实现的,当前程序适用于非嵌套行。检查函数内部的变量 $line。
  • 我认为预期的输出不正确。 ' | snowing ' 部分是与前一个 '{...}' 块的 OR,输出似乎不遵循该规则。换一种说法:似乎没有一种算法方法可以从您的输入到所需的输出。
  • 我也认为正则表达式是进入这里的复杂方式。流式解析器会更容易理解。
  • 根据定义,正则表达式不是您所要求的解决方案,因为您要处理的表达式不是正则表达式。它们的无限和嵌套性质意味着解析器将是比正则表达式更合适的工具。该解析器可能包含一些简单的正则表达式调用,以帮助提取表达式的各个部分,但单个正则表达式字符串无法完成您想要的操作。

标签: php arrays regex split explode


【解决方案1】:

这个类完成了工作,尽管不确定它的效率如何:

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);

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

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

【讨论】:

  • 感谢您的贡献,但这不是我想要的。我已经发布的脚本正在输出$line 变量的所有可能变化(我必须这样做),但我的解决方案不适用于嵌套值。再看一遍帖子,{my {words|sentence}| yours}应该是可以的。
  • @J.Doe 我跑了{my {words|sentence}| yours},可能的输出是my wordsyoursmy sentence。这不是正确的输出吗?
  • 我的错误,对不起,我只是浏览了代码。刚刚检查过它,它的工作原理。虽然这个随机值,但可以将其转换为输出所有可能的变化,对吧?
  • @J.Doe 应该可以,但是代码需要更新。 array_rand($parts) 部分应更改。很抱歉我现在在办公室,所以现在不能重构它。给我几个小时,我会用你真正需要的来更新答案。敬请期待:)
  • 赞赏。同时,我会自己尝试并尝试弄清楚。干杯。
猜你喜欢
  • 2016-07-18
  • 1970-01-01
  • 2013-12-05
  • 2013-07-28
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
相关资源
最近更新 更多