Wyrażenie regularne, które pasuje, tylko gdy jest na końcu

0

Mam mniej więcej takie wyrażenie regularne:

(?:(?:ala\s)(?<Ala>\d+(?:-\d+)?))?\s?(?:(?:kota\s)(?<Kota>\d+(?:-\d+)?))?

Przykładowe dopasowania:

ala 1-2
ala 1
ala 1-2 kota 1-2
ala 1 kota 2
kota 1-2

Teraz chciałabym zmienić to wyrażenie tak, by zakres akceptował tylko wtedy, gdy jest na końcu, czyli poniższe jest poprawne:

ala 1 kota 1-2
ala 1-2

A poniższe nie powinno być złapane w całości:

ala 1-2 kota 1 //dopasowanie: ala 1

Jednocześnie utrudnienie jest takie, że zależy mi na tym, by zakres był w nazwanej grupie (w dalszej części kodu grupy są mocno powiązane z tym, co się dzieje). Gdyby nie to, to zrobiłabym po prostu:

(?:(?:ala\s)(?<Ala>\d+))?\s?(?:(?:kota\s)(?<Kota>\d+))?(?:-\d+)?

Czy jest na to jakiś sprytny myk? Czy lepiej kombinować z przerabianiem tej części, która opiera się o nazwane grupy...?

1

Jeśli dobrze rozumiem, to chcesz czegoś takiego ala \d+-\d+\b czy takiego ala \d+-\d+$? Ciężko jest mi trochę zrozumieć przykłady, które podałaś. Może spróbuj podać linka do https://regex101.com z przykładowym wyrażeniem i tekstem jaki chcesz zmatchować.

0

Chcę uzyskać taki efekt jak tutaj: https://regex101.com/r/1CTOto/1
Ale z zastrzeżeniem, że to co z myślnikiem (w tych przykładach 1-2), powinno być chwycone w nazwanej grupie (Ala lub Kota).

$ nie daje takiego efektu w .NET, ale wygląda na to, że \b daje radę :) Dzięki :)

0

Kurde, głupia sprawa, \b jednak nie daje rady :/ Tak mi się wydawało, bo zrobiłam literówkę w tekście...

Testuję tutaj: http://regexstorm.net/tester
Pattern z \b:

(?:(?:ala\s)(?<Ala>\d+(?:-\d+\b)?))?\s?(?:(?:kota\s)(?<Kota>\d+(?:-\d+\b)?))?

Tekst do testów:

ala 1-2 kota 1
ala 1 kota 1-2
ala 1
ala 1 kota 1

Chcę, żeby na powyższym tekście były następujące dopasowania (pogrubione):

ala 1-2 kota 1
ala 1 kota 1-2
ala 1
ala 1 kota 1

0

@aurel: wychodzi na to, że musisz włączyć matching wieloliniowy i wtedy takie wyrażenie ^[^-]+\d(-\d+|\r?$) zadziała.

0

Problem w tym, że potrzebuję, by 1-2 było przypisane do odpowiedniej nazwanej grupy - albo Ala, albo Kota, zależnie od tego, gdzie taka fraza wystąpi ;)
Gdyby nie ten szkopuł, to użyłabym po prostu: (?:(?:ala\s)(?<Ala>\d+))\s?(?:(?:kota\s)(?<Kota>\d+))?(?:-\d+)?

0

A jaka jest tutaj zasada, że matchujemy "ala 1-2 kota 1" ale "ala 1 kota 1"? Wydaje mi się, że tutaj jest więcej logiki, którą ciężko opisać w samym wyrażeniu regularnym. Jesteś pewna, że parser nie zadziałał by tutaj lepiej? Może podaj faktyczny przykład, bo inaczej nie za bardzo jestem w stanie to jakoś rozwiązać.

0

Faktyczny przykład to jednostki aktów prawnych: art. 1 par. 1-3, art. 1 par. 1, art. 1, par. 1 są prawidłowe, ale art. 1-3 par. 1 już nie i powinno być obcięte do art. 1-3.

Oczywiście możesz mieć rację, że to nie jest zadanie dla wyrażenia regularnego. Wolałam jednak podpytać przed zmianą podejścia, bo działam w istniejącym kodzie i zmiany będą oznaczały ogrom roboty ;)

1

Zawsze możesz rozbić to na 2 części:

  1. Znaleźć wszystkie wystąpienia, nawet uwzględniając false positive.
  2. Przefiltrować wszystkie wyniki odrzucając niepoprawne.

Wydaje mi się, że to może być najprostsze rozwiązanie. Ale w takim ogólnym przypadku wystarczyłoby zwykłe wyszukiwanie w ciągu znaków fraz i następnie parsowanie małych fragmentów.

0

@hauleth dokładnie tak, właściwie to co określiłam jako "ogrom roboty" udało mi się zrobić działające i właśnie leci do testów ;) Faktycznie wystarczyło dodać jeden warunek na odrzucanie nadmiaru.

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