Как написать регулярное выражение для этого сценария? - PullRequest
4 голосов
/ 21 июля 2009

Например, у меня есть строка:

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

Теперь я хочу разделить содержимое на «/» и игнорировать содержимое в «[ ]».

Результат должен быть:

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

Как получить результат с помощью регулярного выражения? Мой язык программирования JavaScript.

Ответы [ 7 ]

3 голосов
/ 21 июля 2009

Вы не можете делать это с регулярными выражениями, потому что это рекурсивно. (Это отвечает на ваш вопрос, теперь, чтобы посмотреть, смогу ли я решить проблему элегантно ...)

Редактировать: aem предупредил меня! : D

Работает до тех пор, пока за каждым [ следует /. не проверяет, что строка имеет правильный формат.

string temp = text.Replace("[/", "[");
string[] elements = temp.Split('/').Select(element => element.Replace("[", "[/")).ToArray();
2 голосов
/ 21 июля 2009

Это работает ...

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/

2 голосов
/ 21 июля 2009

Вы можете сначала перевести двухсимвольную последовательность [/ в другой символ или последовательность, которые, как вы знаете, не появятся во входных данных, затем разбить строку на / Границы, а затем повторно перевести переведенную последовательность обратно в [/ in Строки результата. Это даже не требует регулярных выражений. :)

Например, если вы знаете, что [не появится само по себе в ваших входных последовательностях, вы можете заменить [/ на [на начальном этапе.

1 голос
/ 21 июля 2009

Судя по вашей истории публикаций, я думаю, вы говорите о регулярных выражениях в 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]  

Конечно, я полагаюсь на некоторые упрощающие предположения здесь. Надеюсь, вы дадите мне знать, если какое-то из моих предположений будет неверным, Майк. :)

РЕДАКТИРОВАТЬ: Все еще ожидая решения от Майка о предположениях, но Крис Латс поднял хорошую точку в своем комментарии к 280Z28. На корневом уровне в примере строки есть два места, где вы видите два смежных токена /divN, но на каждом другом уровне токены всегда изолированы друг от друга квадратными скобками. Мое решение, как и у 280Z28, предполагает, что это всегда будет правдой, но что если данные выглядят так?

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

Теперь у нас есть два места, где косая черта без разделителя равна , а не с предшествующей левой квадратной скобкой, но основная идея такова. Начиная с любой точки корневого уровня, если вы сканируете вперед в поисках квадратных скобок, первой, которую вы найдете, всегда будет левая (или открывающая) скобка. Если вы отсканируете назад, вы всегда сначала найдете правую (или закрывающую) скобку. Если оба эти условия не соответствуют действительности, вы не находитесь на корневом уровне. Переводя это на lookarounds, вы получаете это:

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

Я знаю, что это становится довольно мрачно, но я возьму на себя эту чертову рекурсию в любой день недели. ;) Еще одна приятная вещь - вам не нужно ничего знать о токенах, кроме того, что они начинаются с косой черты и не содержат квадратных скобок. Кстати, это регулярное выражение содержит вид сзади, который может соответствовать любому количеству символов; список вариантов регулярных выражений, поддерживающих , которые действительно очень короткие, но .NET может это сделать.

0 голосов
/ 21 июля 2009

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

0 голосов
/ 21 июля 2009

экспериментальный пример, использующий 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

Примечание: в конце есть "/", так что лишь небольшая часть обрезки даст желаемый результат.

0 голосов
/ 21 июля 2009

Не зная, на какой движок регулярных выражений вы нацеливаетесь, я могу только догадываться, что будет работать для вас. Если вы используете .Net, посмотрите здесь: http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx

Если вы используете Perl, посмотрите здесь: http://metacpan.org/pod/Regexp::Common::balanced

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...