Tak, jest to możliwe przy użyciu silnika regex że obsługuje backreferences i warunki.
Pierwsza lista kolejnych numerów może być rozłożona na liście, gdzie każda para numerów jest rzędu:
(?=(?&cons))\d+
(?:,(?=(?&cons))\d+)*
,\d+
tutaj (?=(?&cons))
jest zastępczy predykatu, który zapewnia, że dwie liczby są sobie. To orzeczenie może wyglądać następująco:
(?<cons>\b(?:
(?<x>\d*)
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?:9(?= 9*,\g{x}\d (?<y>\g{y}?+ 0)))*
,\g{x}
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
(?(y)\g{y})
# handle the 999 => 1000 case separately
| (?:9(?= 9*,1 (?<z>\g{z}?+ 0)))+
,1\g{z}
)\b)
Na krótkim wyjaśnieniem, drugi obsługę 999,1000
pary typu sprawa jest łatwiejsza do zrozumienia - jest bardzo szczegółowy opis, jak to działa w this answer concerned with matching a^n b^n. Połączenie między nimi polega na tym, że w tym przypadku musimy dopasować 9^n ,1 0^n
.
Pierwszy przypadek jest nieco bardziej skomplikowany. Największą część z nich obsługuje prosty przypadek zwiększając cyfrę dziesiętną, która jest stosunkowo gadatliwy ze względu na liczbę tych cyfr:
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
Pierwszy blok będzie uchwycić czy cyfra jest N w grupie AN i sekundę blok użyje wtedy warunków warunkowych do sprawdzenia, która z tych grup była użyta. Jeśli grupa aN nie jest pusta, następna cyfra powinna wynosić N + 1.
Pozostała część pierwszego przypadku obsługuje takie przypadki, jak 1999,2000
. To znowu wpada w schemat N 9^n, N+1 0^n
, więc jest to kombinacja metody dopasowywania a^n b^n
i inkrementacji cyfry dziesiętnej. Prosty przypadek 1,2
jest traktowany jako przypadek ograniczający, w którym n = 0.
pełna regex: https://regex101.com/r/zG4zV0/1
Alternatywnie (?&cons)
orzeczenie można zrealizować nieco bezpośrednio, jeśli są obsługiwane rekurencyjne odniesienia podciąg wzorca:
(?<cons>\b(?:
(?<x>\d*)
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?<y>
,\g{x}
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
| 9 (?&y) 0
)
# handle the 999 => 1000 case separately
| (?<z> 9,10 | 9(?&z)0)
)\b)
W tym przypadku dwa gramatyki 9^n ,1 0^n
n> = 1 i prefix N 9^n , prefix N+1 0^n
, n> = 0 są właściwie napisane wprost.
Kompletne alternatywne wyrażenie: https://regex101.com/r/zG4zV0/3
Nice post. Mam ogólne pytanie dotyczące _nested back reference_ To wyrażenie w twoim regex na przykład '(? \ g {y}? + 0)'. Używam silnika _Boost regex_, który jest w większości kompatybilny z PCRE i Perl. Czasami muszę stosować obejścia w określonych sytuacjach. Jednym z nich jest na przykład '(? (? & _ Y)? + 0) (? (DEFINE) (?<_y> \ g {y})) 'Napędza mnie czasem komunikat' undefined backref', że jeśli możliwe jest obejście tego problemu, czemu nie wspierać go w całości. Zastanawiasz się, czy znasz lepsze obejście, które nie wymaga wywołania funkcji? (_workaround https://regex101.com/r/zG4zV0/2_). –
sln
@ sln Niestety, nie znasz mechanizmu doładowania regex. Jeśli dobrze rozumiem, problem polega na tym, że funkcja boost nie obsługuje funkcji backrefs dla grup, które nie zostały jeszcze w pełni dopasowane, prawda? W takim przypadku Twoje obejście wydaje się rozsądne. Dodałem także alternatywne rozwiązanie oparte na rekursywnych odnośnikach podrzędnych, może to działa po wyjęciu z pudełka ... – NikiC
To jest czas kompilacji podczas parsowania: 'grupy, które jeszcze nie zostały (w pełni) przeanalizowane. ' Tak więc odniesienie do jego macierzystej grupy przechwytywania. Rozwiązałem problem, dopuszczając backrefs do tego znaku w chwili otwierania grupy, ale przed dodaniem stanów wewnętrznych za pomocą analizy rekurencyjnej. Dawniej, pozwalało to tylko na backrefs do tego znaku, gdy parsowanie ')' zostało sparsowane. Jest to prosta maska bitowa 'm_backrefs | = 1 << (markid-1)', jeśli nie zostanie znaleziony margines zamykający, generowany jest błąd, a mimo to całość się rozwija. Działa zgodnie z oczekiwaniami. Dodaję to do innych modów, które zrobiłem. – sln