Znajdowanie grup ograniczonych { i } przy pomocy wyrażenia regularnego

0

Mam taki oto regex:
(\{.+?\})*
Jego zadaniem jest znalezienie elementów ograniczonych { oraz }. Mam też testowy tekst:
{1.0 0b1 2006-01-01_12:34:56.789}{1.2345 0b100000 2006-01-01_12:34:56.789}
Problem jest taki, że znajduje tylko drugą grupę. Wystarczy jednak, że dodamy spację pomiędzy i wtedy działa jak powinno. Nie udało mi się jak dotąd ustalić dlaczego. Na logikę nie mam żadnych restrykcji dotyczących białych znaków i według mnie powinno i bez spacji hulać. Jakieś pomysły?

0

http://ideone.com/LenM7E ?

edit: aa bo ty chyba myślisz że ci się grupy zwielokrotnią? o_O

0

Yhm widocznie w phytonie to dziala. Ja sprawdzam tym: https://regex101.com/r/vV3oJ6/2
w C# mam taki sam efekt

EDIT: Zwielokrotnią? Nieeee. Efekt chciałbym właśnie taki jak w ideone.

0

Przecie masz po prawej napisane:

Note: A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data

0
(\{.+?\})

U mnie to działa, po co ci ta gwiazdka?

0

po co Ci też \ przed { i } ?

wystarczy

({.+?})

0
Shalom napisał(a):

Przecie masz po prawej napisane:

Note: A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data

Czyli żeby zrobić tak: ((\{.+?\})+) ? Wtedy się robi jeszcze gorzej: https://regex101.com/r/vV3oJ6/3

MATCH 1

  1. {1.0 0b1 2006-01-01_12:34:56.789}{1.2345 0b100000 2006-01-01_12:34:56.789}
  2. {1.2345 0b100000 2006-01-01_12:34:56.789}

Chyba, że coś źle zrozumiałem

Wizzie napisał(a):
(\{.+?\})

U mnie to działa, po co ci ta gwiazdka?

Bo to jest część większego wyrażenia
(\".+?\")*([^{}\s]+)*(\{.+?\})*

Faktycznie samo to bez gwiazdki działa, ale jak spróbuję usunąć w tym gwiazdkę to kicha (matchuje tylko te w klamrowych nawiasach). Przykładowa treść:

COMMAND STATUS {OBJECT}{OBJECT} "TEXT" "TEXT"

EDIT:
Oczyściłem wyrażenie i teraz wygląda tak: (".+?")*([^{}\s]+)*({.+?})*

0

To co w tej chwili próbujesz zrobić jest zależne od implementacji silnika wyrażeń regularnych. Część z nich po prostu nie zapamiętuje powtarzających się grup i złapie ci tylko ostatnią, a część zapamięta wszystkie (np. w postaci "captures", a nie tylko "groups" jak w implementacji .NETowej).

Także: z jakiego silnika korzystasz i dlaczego nie łapiesz po prostu jednej grupy jednocześnie (tj. (\{*+?\}))?

0
Sarrus napisał(a):

Bo to jest część większego wyrażenia
(\".+?\")*([^{}\s]+)*(\{.+?\})*

Faktycznie samo to bez gwiazdki działa, ale jak spróbuję usunąć w tym gwiazdkę to kicha (matchuje tylko te w klamrowych nawiasach). Przykładowa treść:

COMMAND STATUS {OBJECT}{OBJECT} "TEXT" "TEXT"

Jeżeli pomiędzy grupami może być cokolwiek to spróbuj:
({.+?}).*?

1

http://ideone.com/0ZC0ob

using System;
using System.Text.RegularExpressions;
 
public class Test
{
	public static void Main()
	{
	    var input = "COMMAND STATUS {OBJECT1}{OBJECT2} \"TEXT1\" \"TEXT2\"";
        var regex = "(?<command>.+?) (?<status>.+?) (?<objects>\\{.+?\\})+ (?:(?<texts>\".+?\") ?)+";
 
        var match = Regex.Match(input, regex);
 
        Console.WriteLine("command: {0}", match.Groups["command"]);
        Console.WriteLine("status: {0}", match.Groups["status"]);
 
        foreach (var @object in match.Groups["objects"].Captures)
            Console.WriteLine("object: {0}", @object);
 
        foreach (var text in match.Groups["texts"].Captures)
            Console.WriteLine("text: {0}", text);
	}
}
0

Twój kod @Rev jest jak najbardziej dobry i zastanowię się później czy nie przerobić sobie na coś podobnego. Na razie użyłem innego podejścia:

 var regex = new Regex("(\".*?\"|{.*?}|[^{}\"\\s]+)");
 var matches = regex.Matches(responseString);
 return matches
    .Cast<Match>()
    .Where(match => match.Success && !string.IsNullOrWhiteSpace(match.Value))
    .Select(match => CommandParameter.Parse(match.Value));

Zmiana polega na tym, że jest jedna grupa z alternatywami zamiast trzech z gwiazdkami. Działa wyśmienicie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1