-1

我正在尝试从我们的数据库中获取一些注释行,它们存储为字符串,以“\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
)

我如何将它们结合起来?

4

1 回答 1

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_DOTALL( s) 标志来修改 的含义.,使其也匹配换行符。
  3. 这将使第一个.*匹配一直到文件末尾,所以让它不贪婪:.*?.

现在,您需要匹配所有内容,直到下一个日期模式,但在它之前停止。您可以通过用前瞻表达式结束正则表达式来表达这一点。由于它将分隔您的匹配组,因此您不再需要将其显式放入匹配的模式中。

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

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

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

PS。如果更改文件格式仍然是一种选择,请考虑转换为 csv 格式并使用fgetcsv或类似的方式读取它。

于 2012-11-27T21:18:03.300 回答