如何使用带有preg_match_all的正则表达式将一个模式后的字符串拆分为多个块

时间:2019-06-13 14:41:15

标签: php regex

我将要处理一长串数据,这些数据使用模式(x:y)序列化为块。

但是,我在正则表达式方面苦苦挣扎,并且正在寻找资源来帮助确定如何构造正则表达式来识别出现在字符串中的任何/所有这些块。

例如,给定以下字符串:

$s = 't:user c:red t:admin n:"bob doe" s:expressionsf:json';
  

注意:最后的f:json故意遗漏了一个空格,因为格式可能会随着最终给我的字符串的方式而变化。每个块都可能有间隔,但可能没有。

我如何识别x:y的每个块以以下结果结尾:

Array
(
    [0] => t:user
    [1] => c:red
    [2] => t:admin
    [3] => n:"bob doe"
    [4] => s:expression
    [5] => f:json
)

我用有限的知识测试了各种表情,但还没有取得成功。

我可以使用以下方式成功匹配模式:

  

^ [ctrns]:。+

但是这不幸地匹配了整个字符串。我似乎缺少的部分是如何打破每个区块,同时又保持在两对之间保持空格的能力(请参见n:“ bob doe”示例)。

任何帮助将不胜感激!而且,理想情况下,任何提交都应解释表达式中每个标记的作用,以便我更好地理解这些技术。

我一直在使用https://regexr.com/进行练习。

1 个答案:

答案 0 :(得分:2)

您可以在preg_match_all中使用此正则表达式:

[ctnsf]:(?:"[^"\\]*(?:\\.[^"\\]*)*"|\S+?(?=[ctnsf]:|\s|$))

RegEx Demo

RegEx详细信息:

  • [ctnsf]::匹配ctnsf个字符之一,后跟:
  • (?:"[^"\\]*(?:\\.[^"\\]*)*":匹配带引号的子字符串。这也可以处理转义的引号。
  • |:或
  • \S+?:匹配1个以上非空格字符(非贪婪)
  • (?=[ctnsf]:|\s|$):肯定断言来断言断言中给出的条件之一。

代码:

$re = '/[ctnsf]:(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|\S+?(?=[ctnsf]:|\s|$))/m';
$str = 't:user c:red t:admin n:"bob \\"doe" s:expressionsf:json';

preg_match_all($re, $str, $matches);

// Print the entire match result
print_r($matches[0]);

Code Demo