如何为这种情况编写正则表达式?

时间:2009-07-21 03:34:14

标签: javascript regex

例如,我有一个字符串:

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

现在,我想将内容拆分为“/”,并忽略“[ ]”中的内容。

结果应为:

  1. div1
  2. div2[/div3[/div4]]
  3. div5
  4. div6[/div7]
  5. 如何使用正则表达式获得结果?我的编程语言是JavaScript。

7 个答案:

答案 0 :(得分:3)

您无法使用正则表达式执行此操作,因为它是递归的。 (这回答了你的问题,现在看看我是否可以优雅地解决问题......)

编辑:aem让我失望! :d

只要每个[后跟/,就可以正常工作。它验证字符串的格式是否正确。

string temp = text.Replace("[/", "[");
string[] elements = temp.Split('/').Select(element => element.Replace("[", "[/")).ToArray();

答案 1 :(得分:2)

您可以先将双字符序列[/转换为您知道不会出现在输入中的另一个字符或序列,然后将字符串拆分为/ boundary,然后将翻译后的序列重新转换回[/ in结果字符串。这甚至不需要正则表达式。 :)

例如,如果您知道[在输入序列中不会单独显示,则可以在初始步骤中替换[/] [

答案 2 :(得分:2)

这有效......

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

    }
}

礼貌...... http://retkomma.wordpress.com/2007/10/30/nested-regular-expressions-explained/

答案 3 :(得分:1)

根据您的发布历史判断,我猜您正在谈论C#(.NET)正则表达式。在这种情况下,这应该工作:

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

这假设每个非分隔符/前面都有一个左方括号,就像样本数据一样。

您应该始终指定您正在使用的正则表达式。例如,这种技术需要支持外观的风味。在我的脑海中,包括Perl,PHP,Python和Java,但不包括JavaScript。

编辑:这是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);
    }
  }
}

输出:

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

当然,我在这里依赖于一些简化的假设。如果我的任何假设都错了,我相信你会告诉我,迈克。 :)

编辑:仍在等待迈克关于这些假设的裁决,但Chris Lutz在他对280Z28的评论中提出了一个很好的观点。在示例字符串的根级别,有两个地方可以看到两个连续的/divN标记,但在每个其他级别,标记始终通过方括号彼此隔离。我的解决方案,如280Z28,假设总是如此,但如果数据看起来像这样呢?

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

现在我们有两个地方,非分隔符斜线前面有一个左方括号,但基本的想法是。从任何一点开始,如果你向前扫描寻找方括号,你找到的第一个将始终是一个左(或开口)括号。如果向后扫描,您将始终首先找到正确(或关闭)括号。如果这两个条件都不正确,那么您就不在根级别。将其转化为外观,你得到了这个:

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

我知道它变得非常粗糙,但是我会在一周的任何一天接管那些神圣的递归。 ;)另一个好处是你不必知道任何关于令牌的事情,除了它们以斜杠开头并且不包含任何方括号。顺便说一下,这个正则表达式包含一个可以匹配任意数量字符的lookbehind;支持的正则表达式列表确实很短,但.NET可以做到。

答案 4 :(得分:0)

在不知道您所针对的正则表达式引擎的情况下,我只能猜测哪些适用于您。如果您使用的是.Net,请查看此处:http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx

如果您使用的是perl,请查看此处:http://metacpan.org/pod/Regexp::Common::balanced

答案 5 :(得分:0)

实验示例,使用PHP和拆分方法,但仅在样本字符串上进行测试。

$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 . "/";
    }
}

输出:

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

注意:最后有“/”,所以只需要一点修剪就可以得到理想的结果。

答案 6 :(得分:0)

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