Регулярное совпадение только первое или единственное второе вхождение - PullRequest
2 голосов
/ 05 мая 2019

Мне нужно найти две цифры в строке, но я знаю только, нужны ли первые две цифры или вторые две цифры, не знаю точно, где они находятся в строке и что их окружает.Строки являются датами, но формат, для всех намерений и целей, случайный.
Я до сих пор придумал это:

(?<=\D)\d{1,2}(?=\D)

Это соответствует тому, что мне нужно, но мне нужноостановите сопоставление после первого или второго вхождения, поэтому в этих примерах он не найдет почти все:

2019-01-05 23:59:59
2019 01 05 23:59:59
2019. 01. 05. 23:59:59
2019.01.05. 23:59:59
05-01-2019 23:59:59
5-1-2019 23:59:59
05/01/2019 23:59:59
5/1/2019 23:59:59
5 1 2019 23:59:59
05 1 2019 23:59:59
05. 1. 2019 23:59:59
5. 1. 2019 23:59:59

Здесь в основном я хочу сопоставить либо «1» / «01», либо«5» / «05» в каждой строке.
Я уже искал много форумов, но не могу найти какое-либо решение, которое могло бы помочь, кажется, что везде решение зависит от строки, а не «найти толькоn-е вхождение ".В моем случае это было бы единственной вещью, которая решает проблему, по крайней мере, я не мог придумать какой-либо шаблон, который определенно соответствовал бы каждый раз.Приведенные выше примеры - даже не единственные возможности. Любой способ форматирования даты - это один из них. Единственное, что я знаю, это то, что она одинакова во всех документах, где я хочу искать, в дате всегда есть разделители иэто приходит раньше времени.

Ответы [ 2 ]

1 голос
/ 05 мая 2019

Это выражение может помочь вам получить только первое вхождение желаемого месяца и дня:

[-\s.]+(\d{2})[-\s.]+(\d{2})[\s\S]*

Это не лучшее выражение для этого, однако оно может датьВы общее представление о том, как эти жадные персонажи [\s\S]* проходят через ваш нежелательный символ.

Вы можете просто изменить мои начальные границы по своему усмотрению, вы можете использовать исходное выражение с небольшими изменениями, за которым следует только [\s\S]*.

enter image description here

График

График показывает, как это будет работать:

enter image description here

0 голосов
/ 05 мая 2019

Вы можете сопоставить шаблон типа даты и использовать группы захвата для извлечения части месяца или дня.Часть месяца и дня находится в первой или третьей группе захвата, и для получения согласованных разделителей вы можете использовать обратные ссылки на группы захвата.

Чтобы получить отдельные значения, которые можно разделить на совпадающие, а не цифры \D

(?:\d{4}(([- .]|\. )\d{2}\2\d{2})\.? |(\d{1,2}([-\/ ]|\. )\d{1,2})\4\d{4} )\d{2}:\d{2}:\d{2}
  • (?: Группа без захвата
    • \d{4} Соответствие4 цифры
    • ( Группа захвата 1
      • ( Группа захвата 2
        • [- .]|\. Совпадение либо -, /, пробел ИЛИ точка и пробел
      • ) Закрыть группу захвата 2
    • \d{2}\2\d{2} Матч 2 цифры, обратная ссылка на группу 2, 2 цифры
    • ) Закрыть группу 1
  • \.? Соответствовать необязательной точке и пробелу
  • | Или
  • ( Группа захвата 3
    • \d{1,2} соответствует 1-2 цифрам
    • ([-\/ ]|\.? ) Группа 4, соответствует либо -, /, пробел ИЛИ точка и пробел
  • \d{1,2})\4\d{4} Совпадение 1-2 цифр, обратная ссылка на группу 4 и 4 цифры
  • ) Закрытие группы без захвата
  • \d{2}:\d{2}:\d{2} Совпадение по части, подобной времени,

Regex demo

Например:

let pattern = /(?:\d{4}(([- .]|\. )\d{2}\2\d{2})\.? |(\d{1,2}([-\/ ]|\.? )\d{1,2})\4\d{4} )\d{2}:\d{2}:\d{2}/;
[
  "2019-01-05 23:59:59",
  "2019 01 05 23:59:59",
  "2019. 01. 05. 23:59:59",
  "2019.01.05. 23:59:59",
  "05-01-2019 23:59:59",
  "5-1-2019 23:59:59",
  "05/01/2019 23:59:59",
  "5/1/2019 23:59:59",
  "5 1 2019 23:59:59",
  "05 1 2019 23:59:59",
  "05. 1. 2019 23:59:59",
  "5. 1. 2019 23:59:59"
].forEach(s => {
  let m = s.match(pattern);
  let res = m[1] || m[3];
  console.log(res.split(/\D+/).filter(Boolean));
});

В качестве альтернативы, основанной на вашем паттерне, вместо использования 2 положительных просмотров (?=, вы можете использовать 2 отрицательных просмотра (?!, чтобы утверждать, что слеваи то, что справа, не является цифрой, но это не будет учитывать дату, подобную шаблону.

Чтобы получить только одно совпадение, вы можете опустить глобальный флаг /g

/(?<!\d)\d{1,2}(?!\d)/

Regex demo

Обратите внимание , что внешний вид не поддерживается широко и будет работать в Chrome.

[
  "2019-01-05 23:59:59",
  "2019 01 05 23:59:59",
  "2019. 01. 05. 23:59:59",
  "2019.01.05. 23:59:59",
  "05-01-2019 23:59:59",
  "5-1-2019 23:59:59",
  "05/01/2019 23:59:59",
  "5/1/2019 23:59:59",
  "5 1 2019 23:59:59",
  "05 1 2019 23:59:59",
  "05. 1. 2019 23:59:59",
  "5. 1. 2019 23:59:59"
].forEach(s => console.log(s.match(/(?<!\d)\d{1,2}(?!\d)/)[0]));

Без просмотра за спиной вы можете использовать группу захвата и начать матч с начала строки ^ или без цифры \D:

(?:^|\D)(\d{1,2})(?!\d)

Regex demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...