2011-01-24 8 views
5

Estoy atascado. ¿Por qué el grupo path en este código tiene el valor 2/3/4, no 1/2/3/4? ¿Dónde 1/ ir? ¿Qué parte de la expresión coincide con 1/?Regexes (dialecto .NET): comportamiento extraño de un grupo de captura

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

Esto vuelca "1/2/3/4/5" y luego "1/2/3/4" para mí ... –

+0

@Jon Skeet, me está dando '" 2/3/4 "' para el Ruta, también – bdukes

+0

Aquí hay una captura de pantalla de LINQPad: http://screencast.com/t/dfnJyMLQi9 – thorn

Respuesta

5

Parece que esta es una diferencia de comportamiento entre .NET 3.5 y 4.0. He aquí un programa completo:

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); 
    } 
} 

compilada y ejecutada bajo .NET 3.5:

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

compilada y ejecutada bajo .NET 4:

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

no sé por qué el comportamiento debería variar ...

EDIT: he investigado esto un poco más ... bajo .NET 3.5, el grupo consiste en dos capturas: "1" y "2/3/4". En .NET 4, es la única captura "1/2/3/4".

+6

Usted * no sabe * ?? * incredulous * :) –

+0

Sin duda se parece a una corrección de errores ... – bdukes

0

Hay dos capturas para el grupo Sendero, "1" y "2/3/4" (que yo no entiendo muy bien, ya que estás diciendo cero o uno no proporcionar un cuantificador para ese grupo [y diciendo cero o uno para el grupo de captura numerado alrededor de eso])

0

Lo curioso de su patrón es el uso de ?? después del grupo de rutas. ¿Por qué no estás usando ? solamente? Este metacaracter hace que el elemento anterior sea opcional y se excluye en la coincidencia si es posible.

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

nuevo patrón: @"^-/?(?'folder'((?'path'.+?)/)?[^/]*)/?$"

compilados bajo .NET 3.5 devuelve el resultado deseado. En .NET 4.0 cualquiera de los patrones funciona, lo que indica una diferencia en el comportamiento como Jon pointed out.

+0

Ahmad, sin este personaje obtengo resultados no válidos para cadenas como '" -/16/"'. En este caso, quiero que 'folder' sea' "16" 'y' path' que sea la cadena vacía. – thorn

+0

@thorn entendido ... en ese caso, el comportamiento de .NET 4.0 parece solucionar este problema. –

+0

BTW, mi versión final: '^ - /? (? 'Folder' ((? 'Ruta'. +)/(?! $))? [^ /] *) /? $' – thorn