Por ejemplo, tengo una cadena:

/div1/div2[/div3[/div4]]/div5/div6[/div7]

Ahora quiero dividir el contenido entre "/" e ignorar el contenido en "[ ]".

El resultado debería ser:

  1. div1
  2. div2[/div3[/div4]]
  3. div5
  4. div6[/div7]

¿Cómo puedo obtener el resultado usando expresiones regulares? Mi lenguaje de programación es JavaScript.

4
Mike108 21 jul. 2009 a las 07:34

7 respuestas

La mejor respuesta

Esto funciona...

using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        string testCase = "/div1/div2[/div3[/div4]]/div5/div6[/div7]";
        //string pattern = "(?<Match>/div\\d(?:\\[(?>\\[(?<null>)|\\](?<-null>)|.?)*(?(null)(?!))\\])?)";
        string pattern = "(?<Match>div\\d(?:\\[(?>\\[(?<null>)|\\](?<-null>)|.?)*(?(null)(?!))\\])?)";

        Regex rx = new Regex(pattern);

        MatchCollection matches = rx.Matches(testCase);

        foreach (Match match in matches)
             Console.WriteLine(match.Value);

        Console.ReadLine();

    }
}

Cortesía de... http://retkomma.wordpress.com/2007/10 / 30 / nested-regular-expresiones-explicadas /

2
MyItchyChin 21 jul. 2009 a las 05:04

Ejemplo experimental, usando PHP y enfoque dividido, pero solo probado en una cadena de muestra.

$str = "/div1/div2[/div3[/div4]]/div5/div6[/div7]/div8";
// split on "/"
$s = explode("/",$str);
foreach ($s as $k=>$v){
    // if no [ or ] in the item
    if( strpos($v,"[")===FALSE && strpos($v,"]") ===FALSE){
        print "\n";
        print $v."\n";
    }else{
        print $v . "/";
    }
}

Salida:

div1
div2[/div3[/div4]]/
div5
div6[/div7]/
div8

Nota: hay "/" al final, por lo que solo un poco de recorte obtendrá el resultado deseado.

0
ghostdog74 21 jul. 2009 a las 03:54

A juzgar por su historial de publicaciones, supongo que está hablando de expresiones regulares de C # (.NET). En ese caso, esto debería funcionar:

Regex.Split(target, @"(?<!\[)/");

Esto supone que cada no delimitador / está precedido inmediatamente por un corchete izquierdo, como en sus datos de muestra.

Siempre debe especificar con qué sabor regex está trabajando. Esta técnica, por ejemplo, requiere un sabor que admita mirar hacia atrás. Fuera de mi cabeza, eso incluye Perl, PHP, Python y Java, pero no JavaScript.

EDITAR: Aquí hay una demostración en Java:

public class Test
{
  public static void main(String[] args)
  {
    String str = "/div1/div2[/div3[/div4]]/div5/div6[/div7]";

    String[] parts = str.split("(?<!\\[)/");
    for (String s : parts)
    {
      System.out.println(s);
    }
  }
}

Salida:

div1
div2[/div3[/div4]]
div5
div6[/div7]  

Por supuesto, estoy confiando en algunos supuestos simplificadores aquí. Confío en que me avises si alguno de mis supuestos está mal, Mike. :)

EDITAR: Todavía estoy esperando una decisión de Mike sobre los supuestos, pero Chris Lutz trajo un buen punto en su comentario a 280Z28. En el nivel raíz de la cadena de muestra, hay dos lugares donde se ven dos tokens contiguos /divN, pero en cualquier otro nivel los tokens siempre están aislados entre sí por corchetes. Mi solución, como la 280Z28, supone que siempre será cierta, pero ¿y si los datos se vean así?

/div1/div2[/div3/div8[/div4]/div9]/div5/div6[/div7]  

Ahora tenemos dos lugares donde una barra no delimitadora no está precedida por un corchete izquierdo, pero la idea básica es. Comenzando desde cualquier punto del nivel raíz, si escanea hacia adelante buscando corchetes, el primero que encuentre siempre será un corchete izquierdo (o de apertura). Si escanea hacia atrás, siempre encontrará primero un corchete derecho (o de cierre). Si ambas condiciones no son ciertas, no estás en el nivel raíz. Traduciendo eso a miradas, obtienes esto:

/(?![^\[\]]*\])(?<!\[[^\[\]]*)

Sé que se está volviendo bastante retorcido, pero me haré cargo de esas cosas recurrentes de cualquier día de la semana. ;) Otra cosa buena es que no tienes que saber nada sobre los tokens, excepto que comienzan con barras y no contienen corchetes. Por cierto, esta expresión regular contiene una mirada retrospectiva que puede coincidir con cualquier número de caracteres; la lista de sabores de expresiones regulares que admiten that es muy corta, pero .NET puede hacerlo.

1
Alan Moore 22 jul. 2009 a las 05:33

s/\/(div\d{0,}(?:\[.*?\])?)/$1\n/

0
beggs 21 jul. 2009 a las 04:29

Primero puede traducir la secuencia de dos caracteres [/ a otro carácter o secuencia que sepa que no aparecerá en la entrada, luego dividir la cadena en / límites, luego volver a traducir la secuencia traducida nuevamente en [/ en las cadenas de resultados . Esto ni siquiera requiere expresiones regulares. :)

Por ejemplo, si sabe que [no aparecerá por sí solo en sus secuencias de entrada, puede reemplazar [/ con [en el paso inicial.

2
aem 21 jul. 2009 a las 03:46

No puede hacer esto con expresiones regulares porque es recursivo. (Eso responde a su pregunta, ahora para ver si puedo resolver el problema con elegancia ...)

Editar: aem me avisó! :RE

Funciona siempre que cada [ sea seguido por /. no verifica que la cadena esté en el formato correcto.

string temp = text.Replace("[/", "[");
string[] elements = temp.Split('/').Select(element => element.Replace("[", "[/")).ToArray();
3
Sam Harwell 21 jul. 2009 a las 03:50

Sin saber a qué motor de expresiones regulares está apuntando, solo puedo adivinar qué funcionaría para usted. Si está utilizando .Net, eche un vistazo aquí: http: //blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx

Si está usando perl, eche un vistazo aquí: http://metacpan.org/ pod / Regexp :: Común :: equilibrado

0
szabgab 23 abr. 2014 a las 19:51