2011-01-24 18 views
5

Utknąłem. Dlaczego grupa path w tym kodzie ma wartość 2/3/4, a nie 1/2/3/4? Gdzie było 1/? Która część wyrażenia pasuje do 1/?Regeksy (dialekt .NET): dziwne zachowanie przechwytywania grupy

var re = new Regex(@"^-/?(?'folder'((?'path'.+?)/)??[^/]*)/?$"); 
var m = re.Match("-1/2/3/4/5"); 
m.Groups["folder"].Value.Dump("Folder"); 
m.Groups["path"].Value.Dump("Path"); 
+0

To zrzuca "1/2/3/4/5", a następnie "1/2/3/4" dla mnie ... –

+0

@Jon Skeet, daje mi '" 2/3/4 "' za Ścieżka też – bdukes

+0

Oto zrzut ekranu LINQPad: http://screencast.com/t/dfnJyMLQi9 – thorn

Odpowiedz

5

Wygląda na to, że jest to różnica w zachowaniu między .NET 3.5 i 4.0. Oto kompletny program:

using System; 
using System.Text.RegularExpressions; 

class Test 
{ 
    static void Main() 
    { 
     var re = new Regex(@"^-/?(?'folder'((?'path'.+?)/)??[^/]*)/?$"); 
     var m = re.Match("-1/2/3/4/5"); 
     Console.WriteLine("Folder: " + m.Groups["folder"].Value); 
     Console.WriteLine("Path: " + m.Groups["path"].Value); 
    } 
} 

kompilowany i uruchomić pod .NET 3.5:

Folder: 1/2/3/4/5 
Path: 2/3/4 

kompilowany i uruchomić pod .NET 4:

Folder: 1/2/3/4/5 
Path: 1/2/3/4 

Nie wiem, dlaczego zachowanie powinno się różnić ...

EDYCJA: zbadałem to nieco dalej ... w .NET 3.5, grupa składa się z dwa przechwyty: "1" i "2/3/4". Pod .NET 4 jest to pojedyncze przechwytywanie "1/2/3/4".

+6

Ty * nie wiesz * ?? * z niedowierzaniem * :) –

+0

Z pewnością wygląda na naprawę błędu ... – bdukes

0

Istnieją dwa zrzuty dla grupy ścieżce, "1" i "2/3/4" (który ja nie bardzo rozumiem, skoro jesteś mówiąc zero lub jeden nie zapewniając kwantyfikatora dla tej grupy [mówiąc zero lub jeden dla numerowanej grupy przechwytującej dookoła tego))

0

Dziwną rzeczą w twoim wzorze jest użycie ?? po grupie ścieżek. Dlaczego nie używasz tylko ?? Ten metaznak powoduje, że poprzedni element jest opcjonalny i jeśli to możliwe, jest wykluczany z gry.

@"^-/?(?'folder'((?'path'.+?)/)??[^/]*)/?$" 
           ^
       remove this __| 

Nowy wzór: @"^-/?(?'folder'((?'path'.+?)/)?[^/]*)/?$"

Zestawione pod .NET 3.5 to zwraca pożądanego rezultatu. Pod .NET 4.0 albo działa wzór, który wskazuje różnicę w zachowaniu jako Jon pointed out.

+0

Ahmad, bez tej litery otrzymuję nieprawidłowe wyniki dla ciągów takich jak '" -/16/"'. W tym przypadku chcę, aby 'folder' miał postać' "16" ', a' ścieżka' był pusty. – thorn

+0

@thorn rozumieć ... w tym przypadku zachowanie .NET 4.0 wydaje się rozwiązać ten problem. –

+0

BTW, moja ostateczna wersja: '^ - /? (? 'Folder' ((?? Ścieżka '. +)/(?! $))? [^ /] *) /? $' – thorn