将带有简单标记的字符串分解为数组的最佳方法是什么?

What is the best way to explode a string with simple markup into an array?

在 PHP 中,我想找出最好的方法来获取其中包含一些简单标签的字符串,并将其分解为一个多维数组,每个索引包含另外两个包含项目 [=11 的数组=] 和 text。如果没有特殊标签,tags 将是 null。如果字符串的一部分存在一个(或多个)标签,tags 将包含所有相关标签指示符的 space 分隔列表。

示例:

字符串

The __**quick** brown__ fox jumped __over the__ lazy dog.

处理数组

[
    [
        'tags' => null,
        'text' => 'The ',
    ],
    [
        'tags' => '__ **',
        'text' => 'quick',
    ],
    [
        'tags' => '__',
        'text' => ' brown',
    ],
    [
        'tags' => null,
        'text' => ' fox jumped ',
    ],
    [
        'tags' => '__',
        'text' => 'over the',
    ],
    [
        'tags' => null,
        'text' => ' lazy dog.',
    ],
]

我正在努力思考什么是最好的方法。这个概念看起来很简单,但我想得越多,我就越不知道如何实现它。在 foreach 中使用 preg_match 函数的某种组合是最好的方法,还是有其他选择?任何指向正确方向的帮助将不胜感激。

恶魔并不像画的那么黑

$str = 'The __**quick** brown__ fox jumped __over the__ lazy dog.';

$t = array_map(function($i) { 
     $i = preg_split('/[^ A-Za-z]+\K/', $i,2); 
     if (count($i) == 1) array_unshift($i, null);
     return $i;
     },  preg_split('/[A-Za-z.,]\K(?=[^A-Za-z.,])/', $str));   
print_r($t);

demo

因为您有叠层标记,所以您需要一个堆栈来跟踪叠层级别。没有办法直接用正则表达式来做到这一点,所以只迭代字符串符号可能更容易。

作为开始:

print_r(process("The __**quick** brown__ fox jumped __over the__ lazy dog."));

function process($str) {
  $str = '~~'.$str.'~~';
  $sz = strlen($str);

  $res = array();
  $stack = array();
  $text = '';

  for($n = 0; $n < $sz; $n++) {
    if(strpos('*_~', $c = $str[$n]) === false) {
      $text .= $c;
      continue;
    }
    if($text) {
      $res[] = array('text' => $text, 'tags' => implode(" ", array_slice($stack, 1)));
      $text = '';
    }
    $c .= $str[$n++];
    $c == end($stack) ? array_pop($stack) : $stack[] = $c;
  }
  return $res;
}

输出:

Array
(
    [0] => Array
        (
            [text] => The
            [tags] =>
        )
    [1] => Array
        (
            [text] => quick
            [tags] => __ **
        )
    [2] => Array
        (
            [text] =>  brown
            [tags] => __
        )
    [3] => Array
        (
            [text] =>  fox jumped
            [tags] =>
        )
    [4] => Array
        (
            [text] => over the
            [tags] => __
        )
    [5] => Array
        (
            [text] =>  lazy dog.
            [tags] =>
        )
)

一些注意事项:

  • 此代码假定输入是正确的。它不执行任何检查。
  • 在内部,整个字符串被封装到'~~'标记中。这样,字符串处理以 'end of tag' 条件结束,最后一个待处理的文本块被正确地附加到结果集中。 (请称我为懒狗,因为我这样做了。)然而,这个标记并没有注入到最终结果中。