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?
edit: aa bo ty chyba myślisz że ci się grupy zwielokrotnią? o_O
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.
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
(\{.+?\})
U mnie to działa, po co ci ta gwiazdka?
po co Ci też \
przed {
i }
?
wystarczy
({.+?})
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.0 0b1 2006-01-01_12:34:56.789}{1.2345 0b100000 2006-01-01_12:34:56.789}
-
{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]+)*({.+?})*
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. (\{*+?\})
)?
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:
({.+?}).*?
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);
}
}
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.