Незадължителна група за улавяне в регулярен израз

Имам прост модел за съвпадение с Regex:

{tag:value=text}

tag, value и text са частите, които искам да заснема. Номерът е, че value не е задължително (както и литерала ":" преди)

ето няколко примера:

{tag:value=text}
{tag=text}
{tag:=text}

Първият ред трябва да има "tag" в групата за улавяне на "tag", "value" в групата за улавяне "value" и "text" в групата за улавяне на текст. Другите два реда не трябва да имат никаква група за улавяне на "стойност" (или може да е празна)

Опитах вариации около следния регулярен израз:

{(?<tag>.*):(?<value>.*)?=(?<text>.*)}

Това работи на проби 1 и 3, но не и на втората.

Може да има произволен брой съвпадения в даден текст и искам да ги хвана всичките.

редактиране: Това е извадка от данни, които се опитвам да съпоставя:

Progress: {progress:p1=10%}
Planned duration: {time=10m}
Actors output: {actor:actor1=<nothing to say>}, {actor:actor2=<nothing to say>}
Scene comments: {display=This is a sample scene}

person Stephane    schedule 04.11.2015    source източник
comment
Вижте дали е добре: (tag)(?>:?(value)?=(text)) тук: debuggex.com/r/KPZ6wSqLoGGPRVnK ако е така ще го направя добавете като отговор   -  person Jorge Campos    schedule 04.11.2015
comment
(?<tag>.+)(?>:?(?<value>.+)?=(?<text>.+)) Разбрах, че...   -  person Jorge Campos    schedule 04.11.2015
comment
Можете ли да публикувате някои действителни примерни данни? (Предполагам, че наистина не се опитвате да съпоставите {tag=text} или {tag:value=text}, а реални данни, които съдържат нещо отляво на = и нещо отдясно, с незадължителна стойност, разделена с :. Или наистина буквално съпоставяте {tag=text} ?)   -  person Ken White    schedule 04.11.2015
comment
@KenWhite Опитвам се да съпоставя различни низове, наистина. Ще актуализирам въпроса с някои проби.   -  person Stephane    schedule 05.11.2015


Отговори (2)


Това върши ли работа? Той използва неалчен модификатор ? след .*. Това го кара да съвпада с възможно най-малко символи, вместо с колкото е възможно повече. Тъй като следващият символ е : или =, той ще спре, преди да ги достигне.

{(.*?)(?::(.*?))?=(.*?)}

https://regex101.com/r/fD2eR6/1

Редактиране: както е посочено по-долу, вие търсите наименувани заснемания.

{(?<tag>.*?)(?::(?<val>.*?))?=(?<text>.*?)}

Актуализиран URL адрес: https://regex101.com/r/fD2eR6/2

person miken32    schedule 04.11.2015
comment
OP иска наименувани групи, така че: {(?<tag>.*?)(?::(?<val>.*?))?=(?<text>.*?)} вашето решение с прихващане на наименувани групи - person Jorge Campos; 04.11.2015

Източникът на вашите проблеми идва от използването на .*, което е твърде разрешително (и това може да причини много връщане назад, когато шаблонът работи). Можете да замените всички тези . със съответния клас на отхвърлен символ:

{(?<tag>[^:=]*)(?::(?<value>[^=]*))?=(?<text>[^}]*)}

демонстрация

С клас с отхвърлен символ винаги можете да използвате алчен квантор, защото това е наборът от разрешени знаци, който спира квантора и механизмът на регулярните изрази не трябва да тества за всеки знак дали следващият е :, = или }.

person Casimir et Hippolyte    schedule 04.11.2015
comment
Абсолютно прекрасно. Не ми хрумна да използвам отречените знаци. - person Stephane; 05.11.2015
comment
@Stephane: Да и както можете да видите във връзката, изграждането на вашите модели върху по-ясни класове знаци ще спести много стъпки за механизма на регулярните изрази. - person Casimir et Hippolyte; 05.11.2015