RegExp, чтобы получить строки с переносами строк

Я пытаюсь получить некоторые строки комментариев из нашей базы данных, они хранятся в виде строки, разделенной '\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 ответ

Решение

Точка в регулярном выражении не соответствует переводу строки, поэтому ваш .* идет до конца линии; казалось бы, пустые строки содержат символы новой строки. Так что бросьте .* из вашего шаблона расщепления, а остальное используйте с 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. Это сделало бы первым .* полностью соответствует концу файла, поэтому сделайте его не жадным: .*?,

Теперь вам нужно сопоставить все до следующего шаблона даты, но остановитесь прямо перед ним. Вы можете выразить это, оканчивая регулярное выражение выражением lookahead. Поскольку он будет разделять ваши сопоставленные группы, вам больше не нужно явно указывать его в сопоставленном шаблоне.

Другими словами, попробуйте этот шаблон (я добавил s пометить как суффикс, но, конечно, вы можете передать его отдельно):

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

Комментарий: Я стараюсь избегать взглядов / взглядов сзади, и вы, вероятно, можете понять, почему. Я считаю, что решение, состоящее из двух частей, является более простым и более легким в обслуживании, но здесь есть смысл заглянуть в будущее.

PS. Если изменение формата файла все еще возможно, рассмотрите возможность преобразования в формат CSV и чтения его с fgetcsv или что-то подобное.

Другие вопросы по тегам