2015-01-10 3 views
0

У меня есть следующая строка:регулярного выражения для вложенных структур

bla {{bla {{bla bla {{afsaasg}} }} blabla}} {{bla bla}} bla 

Я хотел бы, чтобы соответствовать

{{bla {{bla bla {{afsaasg}} }} blabla}} 

с регулярным выражением.

но мой регулярных выражений

{{(.*?)}} 

матчи

{{bla {{bla bla}} 

кто может помочь?

Дополнительная информация: Я ожидаю, что одновременно будет не более двух скобок.

Наконец-то я решил это с помощью собственной фукции Java. Perhabs это поможет кому-то:

public static ArrayList<String> getRecursivePattern(String sText, String sBegin, String sEnd) { 

     ArrayList<String> alReturn = new ArrayList<String>(); 

     boolean ok1 = true; 
     boolean ok2 = true; 

     int iStartCount = 0; 
     int iEndCount = 0; 

     int iStartSearching = 0; 

     while (ok1) { 
      int iAnfang = sText.indexOf(sBegin, iStartSearching); 

      ok2 = true; 
      if (iAnfang > -1) { 
       while (ok2) { 

        int iStartCharacter = sText.indexOf(sBegin, iStartSearching); 
        int iEndCharacter = sText.indexOf(sEnd, iStartSearching); 

        if (iEndCharacter == -1) { 
         // Nothing found . stop 
         ok2 = false; 
         ok1 = false; 

        } else if (iStartCharacter < iEndCharacter && iStartCharacter != -1) { 
         // found startpattern 
         iStartCount = iStartCount + 1; 
         iStartSearching = iStartCharacter + sBegin.length(); 
        } else if (iStartCharacter > iEndCharacter && iEndCharacter != -1 || (iStartCharacter == -1 && iEndCharacter != -1)) { 
         iEndCount = iEndCount + 1; 
         iStartSearching = iEndCharacter + sEnd.length(); 

        } else { 
         if (iStartCharacter < 0) { 
          // No End found . stop 
          ok2 = false; 
         } 
        } 
        if (iEndCount == iStartCount) { 
         // found the pattern 
         ok2 = false; 
         // cut 
         int iEnde = iStartSearching;// +sEnd.length(); 
         String sReturn = sText.substring(iAnfang, iEnde); 
         alReturn.add(sReturn); 
        } 
       } 
      } else { 
       ok1 = false; 
      } 
     } 

     return alReturn; 
    } 

Я называю это:

ArrayList<String> alTest=getRecursivePattern("This {{ is a {{Test}} bla }}","{{","}}"); 
    System.out.println(" sTest : " + alTest.get(0)); 
+0

Какой язык вы используете? – anubhava

+0

Я использую это в Java –

+0

Вы хотите, чтобы регулярное выражение соответствовало _only_ вложенным структурам? –

ответ

0

Вы не можете сделать это с регулярными выражениями. Это следствие pumping lemma. Вы должны использовать контекстно-бесплатные грамматики, или, возможно, использовать специальные инструменты (такие как XML/DOM/... parsers).

Вы действительно можете разобрать это для - скажем - три уровня в глубину, но вы не можете позволить этому работать на произвольное количество уровней. Даже тогда лучше использовать контекстно-свободные грамматики (например, компилятор LALR-компилятора), просто потому, что «Это инструменты, предназначенные для анализа таких структур»..

Другими словами, если один день, кто-то может ввести {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ bla }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, и это должно быть действительно, оно скорее всего потерпит неудачу.

Один Sidenote:

Произнесите уровень, например I уровней в глубину, вы можете использовать регулярные выражения, как:

  • для 1: .*?(.*?\{\{.*?\}\}.*?)*.*?
  • для 2: .*?(.*?\{\{.*?(.*?\{\{.*?\}\}.*?)*.*?\}\}.*?)*.*?
  • ...

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

См. Также this discussion для людей, которые хотят анализировать XML/HTML - другой рекурсивный язык - с регулярными выражениями.

Как вы отметили, некоторых регулярного выражения ToolKits действительно предоставляют инструменты для подсчета вещей. Они могут быть найдены в P-языках (PHP, Perl, ...).Эти не являются регулярными выражениями (как определено Kleene, см. this Wikipedia-article о том, что такое реальное регулярное выражение), строго говоря, но упрощенные синтаксические анализаторы. Потому что они не описывают обычный язык . И - в настоящее время - недоступно в большинстве библиотек регулярных выражений, включая Java. Некоторые библиотеки даже предоставляют Тьюринг парсеров, парсеров, чем можно разобрать, что вы можете разобрать алгоритмически, но это на самом деле не рекомендуется для сложных задач ...

+0

Никто не сказал мне этого тысяча раз :-), и ответчик от Авинаша работает. Думаю, мы оба можем многому научиться здесь. –

+0

@ user1344545: Как утверждалось ранее, он работает, если заранее определена максимальная глубина ** **. Ответ также показывает, как построить такое регулярное выражение для произвольной глубины. Но это математически * доказано *, вы не можете сделать этого, когда глубина является произвольной. –

+0

Thats wrong try {{(?: [^ {}] | (? R)) *}} в https://www.regex101.com/ с текстом bla {{bla {{bla bla {{agagsd { {sdgasdgasgd {{sgsagdasd}}}}}} {{afsaasg}}}} blabla}} {{bla bla}} bla. Вы увидите, что он работает рекурсивно. Мне везет. –

0

Разве вы не должны экранировать фигурные скобки? Я делаю в блокноте ++. Во всяком случае, это должно сделать это

\{\{[^{]+\{\{[^{}]+\}\}[^}]+\}\} 
+0

Спасибо. Да, это работает для особого случая. Я укрепил вопрос, потому что я, вероятно, сформулировал неправильно. И знаете, что это работает с решением от Avinash: {{(?: [^ {}] | (? R)) *}} –

1

.NET имеет специальную поддержку для вложенной согласования элемента, так {{(?>[^\{\}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*(?(DEPTH)(?!))}} будет делать то, что вы хотите в C# на любом уровне вложенности, но не Java.

+0

2nd that. И, кроме того, это не - строго говоря - регулярные выражения, а упрощенные парсеры ... –

Смежные вопросы