Избегайте возможных утверждений с регулярным выражением - PullRequest
1 голос
/ 27 октября 2019

Как заменить часть строки, избегая номеров года (например, 2019 или 2019-2020) перед первым появлением косой черты с помощью регулярных выражений

//something is wrong here
preg_replace('/^[a-z0-9\-]+(-20[0-9]{2}(-20[0-9]{2})?)?/', '$1', $input_lines);

Требуется:

abc-def / что-то / еще / [вкл. косая черта, если перед ней нет символа]

abc-def- 2019 / что-то / еще /

abc-def- 2019-2020/ что-то / еще /

abc-def-125- 2019 / что-то / еще /

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Мое первоначальное закрытие было недостаточным для удовлетворения всех требований. Да, у вас есть жадная проблема с квантификатором, но есть еще что-то, что нужно обработать.

Код: ( Demo ) ( Regex101 Demo )

$tests = [
    'abc-def/something/else/',
    'abc-def-2019/something/else/',
    'abc-def-2019-2020/something/else/',
    'abc-def-125-2019/something/else/'
];

var_export(
    preg_replace('~^(?:[a-z\d]+-?)*?(?:/|(?=20\d{2}-?){1,2})~', '', $tests)
);

Вывод:

array (
  0 => 'something/else/',
  1 => '2019/something/else/',
  2 => '2019-2020/something/else/',
  3 => '2019/something/else/',
)

Мой шаблон соответствует буквенно-цифровым последовательностям, за которыми может следовать дефис - подшаблон, который может повторяться ноль или более раз («отдача», то есть не жадность, когдавозможно).

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

Если это не подходит для данных ваших реальных проектов, вам нужно будет предоставить все более и более точные образцы для тестирования, по которым выявляются дополнительные случаи.

0 голосов
/ 29 октября 2019

Если косая черта должна присутствовать, и она должна прекратиться после первого вхождения в 2019 или 2020 году, вы можете использовать:

^(?=[a-z\d-]*/)[a-zA-Z013-9-]+(?>2(?!0(?:19|20)(?!\d))|[a-zA-Z013-9-]+)*/?

В отдельных частях, которые будут выглядеть как

  • ^ Начало строки
  • (?=[a-z\d-]*/) Утверждение о наличии /
  • [a-zA-Z013-9-]+ Соответствие 1+ раз любому из перечисленных (обратите внимание, что 2 не является
  • (?> Атомная группа
    • 2(?!0(?:19|20)(?!\d)) Совпадение 2 и утверждение, что справа не 019 или 020
    • | Или
    • [a-zA-Z013-9-]+ Совпадение 1+ раз с любым из перечисленных
  • )* Закрыть группу и повторить 0+ раз
  • /? Совпадение необязательно /

Regex demo | Php demo

Ваш код может выглядеть как

preg_replace('~^(?=[a-z\d-]*/)[a-zA-Z013-9-]+(?>2(?!0(?:19|20)(?!\d))|[a-zA-Z013-9-]+)*/?~', '', $input_lines);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...