【问题标题】:Deep (infinite) split words using regex使用正则表达式进行深度(无限)拆分词
【发布时间】:2016-07-18 13:20:09
【问题描述】:

假设我有:

$line = "{This is my {sentence|words} I wrote.}"

输出:

This is my sentence I wrote.  
This is my words I wrote.  

但是,正则表达式应该匹配深层和嵌套值并拆分这些值,例如:

$line = "{This is my {sentence|words} I wrote on a {sunny|cold} day.}";

输出:

This is my sentence I wrote on a sunny day.  
This is my sentence I wrote on a cold day.  
This is my words I wrote on a sunny day.
This is my words I wrote on a cold day.  

我的第一个方法是在下面的代码中爆炸,但结果不合适:

$res = explode("|", $line);  

建议?谢谢。

编辑:以下几行:

$line = "{This is my {sentence|words} I wrote on a {sunny|cold} day.}";
$regex = "{[^{}]*}";
$match = [];

preg_match($regex, $line, $match);

var_dump($match);  

如前所述,它可以无限,所以没有限制,适合 for 循环。

【问题讨论】:

  • 我认为您可以创建一个函数,替换 /{[^{}]*}/ 的第一个匹配项并返回匹配项及其索引...然后,虽然返回不是 -1 ,你不断地爆炸|...当然你需要一个数组来推送每个新的sentence(由插入到函数返回的索引中的一个爆炸值组成)
  • $res = explode("|", $line, 2);
  • 我猜嵌套层数可以是任意的,对吧?喜欢$line = "{This is my {sentence|words} I wrote on a {{very|not so} sunny|{freezing|rather} cold} day.}";
  • @WiktorStribiżew 确实。

标签: php regex split explode


【解决方案1】:

看看这个。我通过用%s 替换你的模式并使用vsprintf 来完成它,然后递归循环匹配。

我在代码中放了很多 cmets...理解递归通常是一件很费脑筋的工作。

Here is a working example.

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


// function to find patterns in the line. Takes $line by reference to replace pattern matches with a vsprintf placeholder
function getMatches(&$line) {
    // remove beginning and trailing brackets on the main sentence
    $line = trim($line, '{}'); 

    // initialize variable that will hold the list of pattern matches
    $matches = null;

    // look for an opening curly brace and skip everything until the ending curly brace
    $pattern = '/\{[^}]+\}/';

    // find all matches and put them in $matches
    preg_match_all($pattern, $line, $matches);

    // preg_match_all nests one level deeper than we need
    $matches = $matches[0];

    // replace all matches with a %s placeholder
    $line = preg_replace($pattern, '%s', $line);

    // split each of the matches by vertical pipe
    foreach ($matches as $index => $match) {
        $matches[$index] = explode('|', trim($match, '{}'));
    }

    return $matches;
}


// recursive function. $args will be used as the second argument to vsprintf
function printWords(array $args, array $matches, $line) {
    // get the first element in the array of $matches, remove it from the array
    $current = array_shift($matches);

    // keep track of the current $args index for this recursive iteration
    $currentArgIndex = count($args);

    // loop through each of the words in the current set of matches
    foreach ($current as $word) {
        // update $args and set the vsprintf argument at this iteration's position to the next word in the set of words
        $args[$currentArgIndex] = $word;

        if (!empty($matches)) {
            // repeat this process (recursively) until we are at the end of the list of matches
            printWords($args, $matches, $line);
        } else {
            // if this is the last match in the line, echo the sentence with all args from previous recursive iterations added
            echo vsprintf($line, $args) . '<br />';
        }
    }
}

输出:

这是我在大热天写的一句话。 这是我在一个炎热的夜晚写下的一句话。 这是我在寒冷的一天写下的一句话。 这是我在一个寒冷的夜晚写下的一句话。 这是我在大热天打出的一句话。 这是我在炎热的夜晚打出的一句话。 这是我在寒冷的一天打出的一句话。 这是我在一个寒冷的夜晚打出的一句话。 这是我在大热天写的声明。 这是我在一个炎热的夜晚写下的声明。 这是我在寒冷的一天写下的声明。 这是我在一个寒冷的夜晚写下的声明。 这是我在大热天打出的声明。 这是我在一个炎热的夜晚输入的声明。 这是我在寒冷的一天打出的声明。 这是我在一个寒冷的夜晚打出的声明。

【讨论】:

  • 疯了。喜欢你的解决方案。
  • 不错的解决方案,虽然这不适用于嵌套级别。
  • @JamesBuck:你是对的。虽然 OP 在他的问题中确实使用了“嵌套”这个词,但我没有看到任何表明他确实需要这个词的例子,我也想不出一个例子,当你需要嵌套级别来解决这类问题时。所以我认为他并不是真的意味着“嵌套”。
  • @Travesty3 我没有。但是我仍然对使用正则表达式的嵌套值的方法感到好奇。例如像这样的行:{ It is { raining { and streets are wet } | snowing { and streets are { slippy | white }}}。明天会很好{天气|走 }。 }`,输出应该类似于this。我可以弄清楚如何处理空间而不是嵌套级别。
猜你喜欢
  • 2016-07-24
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 2022-01-22
相关资源
最近更新 更多