正则表达式提取嵌套元素

时间:2013-07-11 14:57:44

标签: php regex nested

我有包含以下结构的文本文件

{1,"StructEx",
[{1,"Element_1",[{2,"name","exampleName"},{3,"exampleValue",1},{2,"exampleComment","foo"}]},
[{1,"Element_2",[{2,"name","exampleName2"},{3,"exampleValue",2},{2,"exampleComment","bar"}]}]}

括号中的第一个值是数据类型。 我需要返回的regex表达式(通过几次迭代) StructEx中的所有元素,所以我可以将它打包成类似的东西

["StructEx"]=>
array(2) {
["Element_1"]=>
array(3) {
  ["name"]=>
  string(11) "exampleName"
  ["exampleValue"]=>
  int(1)
  ["exampleComment"]=>
  string(3) "foo"
}
["Element_2"]=>
array(3) {
  ["name"]=>
  string(12) "exampleName2"
  ["exampleValue"]=>
  int(2)
  ["exampleComment"]=>
  string(3) "bar"
}
}

1 个答案:

答案 0 :(得分:1)

假设嵌套是任意深的,那么答案是不,你不能用正则表达式解析这种文本文档。如果深度是有限的,那很痛苦,但是可行。

为什么会这样?

字母

为了更详细地回答你的问题,让我们介绍一些令人敬畏的干燥理论。

让我们将字母表Σ定义为非空符号集(技术上更正确的定义来自类别理论,将字母表视为非空的自由对象,但为了论证,这个定义就足够了

在我们的字母表Σ中,我们可以在字母表中定义一组所有有限字符串(读取:单词),即:

  

Σ= {s 1 ,s 2 ,...,s n }

     

Σ* = {ε}∪{s i1 s i2 ... s im | s ik ∈Σ,m> 0,1≤k≤n},其中ε是空字符串

例如,这意味着如果我们有一个字母Σ = {a, b, c},Σ*中的某些字词将是aaaaaaabababa,而不是abd,因为我们甚至不知道d存在。

正则表达式&语言

鉴于字母表Σ,我们有正则表达式,如ab*|c。我正在跳过正则表达式的正式定义,以减少它的混乱,所以让我们假设它是我们普通的“实用”正则表达式。

每个正则表达式定义定义常规语言,例如在此示例中,语言由单词aabcabbbbbc组成,但不包含abc

有限自动机

每种常规语言都可以表示为finite automaton,这是一种可以识别正则表达式的设备。对于前面提到的正则表达式ab*|c,自动机看起来像这样:

ab*|c

0是开始状态,双圈是接受状态。简而言之,自动机在状态0开始消耗一个单词的每个字母并根据过渡箭头移动。如果它最终处于接受状态,我们说接受字符串。否则,我们说它拒绝它。

所以在这种情况下,将字符串abb送入我们的机器:

  1. 从状态0开始
  2. 使用a,转到州1
  3. 使用b,转到州3
  4. 使用b,转到州3
  5. 字符串为空且状态3为接受状态,因此本机接受字符串,或者等效地,我们的正则表达式模式匹配字符串。
  6. 让我们看看当我们将abc送入我们的机器时会发生什么:

    1. 从状态0开始
    2. 使用a,转到州1
    3. 使用b,转到州3
    4. 消耗c,无处可动,字符串被拒绝
    5. 所以我们的正则表达式与abc不匹配。所有这些都与实际正则表达式基本相同,并附加了一些理论。

      等价

      有一个定理指出每种常规语言都是有限自动机可识别的。这意味着,如果存在可以匹配所需模式的常规语言(和基础正则表达式),那么应该是一个等价的有限自动机。

      那么,为什么不呢?

      但是你的模式中的嵌套具有无限的深度。因此,您需要一个无限大的有限自动机,它等同于常规语言,这与有限自动机的定义相矛盾。

      参考

      1. Regex & Automata
      2. 声明

        正如你所看到的,我跳过了正则表达式的归纳定义,类别理论视角下的有限自动机,操作中的闭包以及其他一些正式的东西。欢迎您在上述参考链接中阅读相关内容。