RegEx获取换行符

时间:2012-11-27 18:38:40

标签: php regex preg-split

我正在尝试从数据库中获取一些注释行,它们存储为字符串,以'\ n'分隔。不幸的是,在一些评论中包含文本 - 也包含'\ n',我不会将它们分开。

示例评论如下:

27.11.2012 13:19 (MB): test123
27.11.2012 13:20 (MB): test456
27.11.2012 13:21 (JA): test789
lalala
lululu
27.11.2012 13:22 (JA): test10

现在我尝试使用reg exp和preg_split()来区分它们:

#(\d{2}\.\d{2}\.20[0123]{2} \d{2}:\d{2} \([A-Z]{2,3}\): .*)#
(PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)

但我得到

Array
(
    [0] => 27.11.2012 13:19 (MB): test123
    [1] => 
    [2] => 27.11.2012 13:20 (MB): test456
    [3] => 
    [4] => 27.11.2012 13:21 (JA): test789
    [5] => 
lalala
lululu
    [6] => 27.11.2012 13:22 (JA): test10
)

如何将它们合并?

1 个答案:

答案 0 :(得分:0)

正则表达式中的点与换行符不匹配,因此您的.*会转到该行的末尾;看似空的行包含换行符。因此,从您的拆分模式中删除.*,并将其余部分与PREG_SPLIT_DELIM_CAPTURE一起使用。

(\d{2}\.\d{2}\.20[0123]{2} \d{2}:\d{2} \([A-Z]{2,3}\):)

每一行将在冒号处分成两部分。然后,您可以成对加入字符串以获取原始行(或者在您需要将字段分开时,可以省去在程序的下一步中拆分它们的麻烦。)

如果你真的讨厌拆分输入行的想法:

  1. 使用preg_match_all代替分割。
  2. 添加PCRE_DOTALLs)标志以修改.的含义,以便它也匹配换行符。
  3. 这会使第一个.*匹配一直到文件末尾,因此请将其设为非贪婪:.*?
  4. 现在,您需要匹配所有内容,直到下一个日期模式,但在之前停止。您可以通过使用前瞻表达式结束正则表达式来表达这一点。由于它会将匹配的组分开,因此您不再需要将其明确地放在匹配的模式中。

    换句话说,尝试这种模式(我添加了s标志作为后缀,但当然你可以单独传递它:)

    /(.*?)\n(?=\d{2}\.\d{2}\.20[0123]{2} \d{2}:\d{2} \([A-Z]{2,3}\):)/s
    

    评论:我尽可能避免前瞻/后视,你可能会明白为什么。我发现两部分解决方案更简单,更易于维护,但前瞻性很有意义。

    PS。如果仍然可以选择更改文件格式,请考虑转换为csv格式并使用fgetcsv或类似内容进行阅读。