Удалите из строки все, кроме даты с определенным шаблоном

Я пытаюсь удалить все, кроме даты (дд-мм-гггг) из строки, которую я извлекаю из базы данных в foreach.

Я мог бы просто удалить весь текст ([A-Z] [a-z] и т. д.), Но между текстом тоже есть числа.

$strings = [
    'Originele startdatum ',
    'Op verzoek van klant de ingangsdatum gelijkgetrokken met alle andere abonnementen zodat er maar 1 factuur wordt verstuurd.'
];

$result[] = [
    'AboOpmerking' => str_replace($strings, '', $row['AboOpmerking']),
];

Нетронутые струны выглядят так:

Пример 1:

Originele startdatum 3-10-2017

Пример 2:

Originele startdatum 1-1-2014 Op verzoek van klant de ingangsdatum gelijkgetrokken met alle andere abonnementen zodat er maar 1 factuur wordt verstuurd.

Я нашел это регулярное выражение, но не знаю, как его использовать, потому что оно дает мне пустой массив, когда я печатаю $matches.

^([0]?[1-9]|[1|2][0-9]|[3][0|1])[./-]([0]?[1-9]|[1][0-2])[./-]([0-9]{4}|[0-9]{2})$

Вы пытаетесь сопоставить или пытаетесь удалить? Какой должен быть точный вывод?

revo 30.03.2018 10:13

Это очень сложное регулярное выражение. Будет ли работать $date = preg_replace("([^0-9-])", "", $stringWithDate);

Alexey Chuhrov 30.03.2018 10:14

@DanMiller Нет, потому что, как я сказал в своем вопросе, в тексте могут быть числа после даты, и это, похоже, соответствует всем числам и -

Kees Sonnema 30.03.2018 10:15

Вы пытаетесь сделать это (?<!\S)\d+-\d+-\d{4}(?!\S)? regex101.com/r/XyECCO/1

revo 30.03.2018 10:19

@revo Спасибо за это. На данный момент дата не будет иметь другой формат, поэтому принятый ответ меня устраивает. Но я сохраню и эту, спасибо.

Kees Sonnema 30.03.2018 10:51

Я думаю, вы никоим образом не подтверждаете. Вы просто пытаетесь соответствовать. Таким образом, вам не нужно регулярное выражение-монстр для сопоставления дат. Однако вы можете быть более конкретными, Виктор Стрибьев не был вынужден комментировать предоставленное мной регулярное выражение, но, чтобы отложить его, вы можете немного изменить вышеупомянутое регулярное выражение (?<!\d)\d{1,2}-\d{1,2}-\d{4}(?!\d). Тебе лучше использовать это вместо своего.

revo 30.03.2018 11:07

Спасибо, пересмотрю, что буду использовать позже.

Kees Sonnema 30.03.2018 11:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
7
410
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете заменить ^ (который соответствует Начало местоположения строки) и $ (который соответствует конец местоположения строки) на \b (границы слов), чтобы сопоставить подстроки даты как целые слова, и использовать preg_match (для извлечения только первого совпадения) или preg_match_all (если их больше одного):

preg_match('~\b(?:0?[1-9]|[12][0-9]|3[01])([./-])(?:0?[1-9]|1[0-2])\1(?:[0-9]{4}|[0-9]{2})\b~', $s, $matches);

См. демонстрация регулярного выражения

Альтернативой границам слов могут быть поисковые пути (?<!\d) и (?!\d) (которые могут быть полезны, если даты могут быть приклеены к буквам или помещены между символами подчеркивания):

preg_match('~(?<!\d)(?:0?[1-9]|[12][0-9]|3[01])([./-])(?:0?[1-9]|1[0-2])\1(?:[0-9]{4}|[0-9]{2})(?!\d)~', $s, $matches);

Оба выглядят хорошо, я думаю, что второй будет более надежным, поэтому я выберу этот. Что именно делает ~?

Kees Sonnema 30.03.2018 10:12

@KeesSonnema Это разделители регулярных выражений. Они разделяют части регулярного выражения: 1) действие, 2) шаблон и 3) флаги / параметры.

Wiktor Stribiżew 30.03.2018 10:23

Я знаю, собирался.

Kees Sonnema 30.03.2018 10:47

@KeesSonnema BTW, revo предлагает более простое регулярное выражение, которое может извлекать подстроки, похожие на даты. (?<!\S)\d+-\d+-\d{4}(?!\S) соответствует 1+ цифрам, -, 1+ цифрам, - и 4 цифрам, если они заключены в пробел (поэтому совпадений внутри знаков препинания или букв нет), и может совпадать со строками 122432345-42343453254564-2456.

Wiktor Stribiżew 30.03.2018 10:49

Как было предложено, есть альтернатива, в которой вы можете сопоставить дату, например формат \d{1,2}-\d{1,2}-\d{4}, и создать DateTime и, возможно, указать формат, чтобы убедиться, что это действительная дата.

Чтобы заменить только первую дату, вы можете использовать preg_match и preg_replace и указать 1 в качестве четвертого параметра, чтобы выполнить только 1 замену.

$strings = [
    'Originele startdatum 3-10-2017',
    'Originele startdatum 3-10-2017 3-10-2018 ',
    'Originele startdatum 1-1-2014 Op verzoek van klant de ingangsdatum gelijkgetrokken met alle andere abonnementen zodat er maar 1 factuur wordt verstuurd.'
];

$pattern = '/\d{1,2}-\d{1,2}-\d{4}/';
foreach ($strings as $string) {
    if (preg_match($pattern, $string, $matches) === 1 && false !== DateTime::createFromFormat('d-m-Y', $matches[0])) {
        echo preg_replace($pattern, "", $string, 1) . "<br>";
    }
}

Спасибо, пересмотрю, что буду использовать позже.

Kees Sonnema 30.03.2018 11:52

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