На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

Руководство по началу работы. Фиксация regex группы. Reluctant операторы

Операторы ?, +, и * являются по умолчанию "жадными". Таким образом, они пытаются соответствовать такому большому вводу насколько возможно. Иногда это не то, чего мы хотим. Рассмотрим следующий список пап римских пятого столетия:

popesArray = [
    "Pope Anastasius I 399-401",
    "Pope Innocent I 401-417",
    "Pope Zosimus 417-418",
    "Pope Boniface I 418-422",
    "Pope Celestine I 422-432",
    "Pope Sixtus III 432-440",
    "Pope Leo I the Great 440-461",
    "Pope Hilarius 461-468",
    "Pope Simplicius 468-483",
    "Pope Felix III 483-492",
    "Pope Gelasius I 492-496",
    "Pope Anastasius II 496-498",
    "Pope Symmachus 498-514"
]

Первая попытка на регулярное выражение анализирует название  (без порядкового номера либо модификатор) и годы каждого папы римского может быть следующим:

/Pope (.
*)(?: .*)? ([0-9]+)-([0-9]+)/

Который распадается как:

/ Pope (.*) (?: .*)? ([0-9]+) - ([0-9]+) /
начните выражение Папа римский фиксируйте некоторые символы группа некадра: пространство и некоторые символы фиксируйте число - фиксируйте число конец выражения

Мы надеемся, что тогда первая группа кадра будет просто именем Папы Римского в каждом примере, но, как выясняется, он захватывает слишком много ввода. Например первый папа римский разбивается следующим образом:

/ Pope (.*) (?: .*)? ([0-9]+) - ([0-9]+) /
начните выражение Папа римскийAnastasius I  399 - 401 конец выражения

Ясно первая группа кадра фиксирует слишком большой ввод. Мы только хотим фиксировать Anastasius, и модификаторы должны быть зафиксированы второй группой кадра. Еще один способ  состоит в том, что первая группа кадра должна должны охватывать небольшой ввод насколько возможно, чтобы все еще соответствовать. В этом случае это было бы все до следующего пространства. Java регулярные выражения позволяют нам сделать это, используя "reluctant" версии *, + и ? операторов. Для того чтобы сделать один из этих операторов reluctant, просто добавьте ? после его (сделать *?, +? и ??). Таким образом, наши новые регулярные выражения будет:

/Pope (.*?)(?: .*)? ([0-9]+)-([0-9]+)/

Теперь взглянем на наши новые регулярные выражения в самых сложных вариантах, один перед Папой Hilarius (реальный шутник), разбивается следующим образом:

/ Pope (.*?) (?: .*)? ([0-9]+) - ([0-9]+) /
начните выражение Папа римский Leo I the Great 440 - 461 конец выражения

Который является тем, что мы хотим.

Так что для проверки, мы будем использовать код:

popesArray = [
    "Pope Anastasius I 399-401",
    "Pope Innocent I 401-417",
    "Pope Zosimus 417-418",
    "Pope Boniface I 418-422",
    "Pope Celestine I 422-432",
    "Pope Sixtus III 432-440",
    "Pope Leo I the Great 440-461",
    "Pope Hilarius 461-468",
    "Pope Simplicius 468-483",
    "Pope Felix III 483-492",
    "Pope Gelasius I 492-496",
    "Pope Anastasius II 496-498",
    "Pope Symmachus 498-514"
]
myClosure = {
 myMatcher = (it =~ /Pope (.*?)(?: .*)? ([0-9]+)-([0-9]+)/);
 if (myMatcher.matches())
  println(myMatcher[0][1]+": "+myMatcher[0][2]+" to "+myMatcher[0][3]);
}
popesArray.each(myClosure);

Попробуйте этот код с оригинальным регулярным выражением, чтобы видеть сломанный вывод.

 

наверх