根据正则表达式替换数组中的数据

Posted

技术标签:

【中文标题】根据正则表达式替换数组中的数据【英文标题】:Replace data in array based on regex 【发布时间】:2020-07-01 13:50:20 【问题描述】:

我有下一个包含数据的数组(它是动态生成的)。 现在我想做一些魔术并调整数组。

array(1) 
  ["table"]=>
  array(3) 
    ["header"]=>
    array(4) 
      [0]=>
      array(1) 
        ["c"]=>
        string(4) "Naam"
      
      [1]=>
      array(1) 
        ["c"]=>
        string(7) "Functie"
      
      [2]=>
      array(1) 
        ["c"]=>
        string(13) "Nevenfuncties"
      
      [3]=>
      array(1) 
        ["c"]=>
        string(34) " commissies"
      
    
    ["caption"]=>
    bool(false)
    ["body"]=>
    array(3) 
      [0]=>
      array(4) 
        [0]=>
        array(1) 
          ["c"]=>
          string(16) "*|class:orange|*"
        
        [1]=>
        array(1) 
          ["c"]=>
          string(6) "dsasad"
        
        [2]=>
        array(1) 
          ["c"]=>
          string(0) ""
        
        [3]=>
        array(1) 
          ["c"]=>
          string(0) ""
        
      
      [1]=>
      array(4) 
        [0]=>
        array(1) 
          ["c"]=>
          string(4) "brrr"
        
        [1]=>
        array(1) 
          ["c"]=>
          string(6) "adsdsa"
        
        [2]=>
        array(1) 
          ["c"]=>
          string(0) ""
        
        [3]=>
        array(1) 
          ["c"]=>
          string(0) ""
        
      
      [2]=>
      array(4) 
        [0]=>
        array(1) 
          ["c"]=>
          string(6) "dsasad"
        
        [1]=>
        array(1) 
          ["c"]=>
          string(6) "dsadas"
        
        [2]=>
        array(1) 
          ["c"]=>
          string(4) "dsad"
        
        [3]=>
        array(1) 
          ["c"]=>
          string(0) ""
        
      
    
  

当我们查看 ['header'] 时,它包含 ['c'](单元格数据)。这可以是文本,也可以是标签。 例如:*|class:orange|* here some text

现在我想将它们拆分并覆盖 ['c'] 如果它包含 '|class:orange|'。 所以当你有这个时:

   array(1) 
        ["c"]=>
        string(7) "*|class:orange|* hello"
      

会变成这样:

   array(2) 
        ["c"]=>
        string(7) "hello",
        ["class"]=>
        string(7) "orange",
      

这样我可以拆分类并将其添加到数组中。但我被困在 preg_match 上。

foreach ($table as &$row) 

    foreach ($row['header'] as &$header) 
//        $header['class'] = 123;

        preg_match('/\*\|class:([^\|])\|\*/', $header['c'], $matches);

    

我需要做两件事

向数组 ($header['class']) 添加一个属性,类位于 class:example 之后。 我需要替换 $header['c'] 使其不包含 *|class:orange|* 并且仅包含其余文本。

【问题讨论】:

模式可以是这样的\*\|class:([^\|]+)\|\*\h*(.+)得到2个捕获组regex101.com/r/NvEU5M/1 谢谢,我已经在\*\|class:([^\|]+)\|\*\h*(.*)修改了,所以不需要空格 不客气,我已将其添加为答案的更新。 【参考方案1】:

不需要正则表达式(还)。可以通过分隔符定位找到标签:

foreach ($row['header'] as &$header) 
    $str = $header['c'];

    $tagged = substr($str, 0, 2) === '*|' && $pos = strpos($str, '|* ');
    if (!$tagged)  continue; 

    [$tag, $value] = explode(':', substr($str, 2, $pos - 2));
    $header['c']  = substr($str, $pos + 3);
    $header[$tag] = $value;

【讨论】:

【参考方案2】:

例如,您可以使用 2 个捕获组并将它们用作 c 和新类键的值。

对于第二个捕获组,您可以确保使用 \S 匹配至少一个非空白字符

注意重复字符类 1 次或更多次,并且不必转义字符类中的管道。

\*\|class:([^|]+)\|\*\h*(\S.*)

或者如果第 2 组后面的内容可以是可选的:

\*\|class:([^\|]+)\|\*\h*(.*)

Regex demo

解释第一模式

\*\|匹配*| class: 字面匹配 ([^|]+) 捕获组 1,匹配除 | 之外的任何字符 1+ 次 \|\*\h* 匹配 |* 后跟 0+ 个水平空白字符 (\S.*) 捕获组 2,匹配一个非空白字符和 0+ 次除换行符以外的任何字符

Regex demo | php demo

示例代码

$array = [
    "c" => "*|class:orange|* hello"
];

$pattern = "~\*\|class:([^|]+)\|\*\h*(\S.*)~";
foreach ($array as $key => $string) 
    if (preg_match($pattern, $string, $matches)) 
        $array[$key] = $matches[2];
        $array["class"] = $matches[1];
    


print_r($array);

输出

Array
(
    [c] => hello
    [class] => orange
)

【讨论】:

以上是关于根据正则表达式替换数组中的数据的主要内容,如果未能解决你的问题,请参考以下文章

如何将此正则表达式替换从替换单个单词更改为替换单词数组?

根据匹配用替换字符串替换字符串中的正则表达式模式

织梦数据库内容替换,正则去掉文章内容中的img标签

js正则匹配替代指定字符(根据img标签的src中的命名规则,用正则表达式替换成下面格式的文字)

js正则匹配替代指定字符(根据img标签的src中的命名规则,用正则表达式替换成下面格式的文字)

正则表达式中的插入操作