Javascript dynamic regex, строка соответствия между скобками, которые имеют префикс [duplicate]

Функция

promiseA then возвращает новое обещание (promiseB), которое немедленно разрешается после разрешения promiseA, его значение является значением того, что возвращается из функции успеха в promiseA .

В этом случае promiseA разрешается со значением - result, а затем немедленно разрешает promiseB со значением result + 1.

Доступ к значению promiseB выполняется так же, как мы получили доступ к результату promiseA.

promiseB.then(function(result) {
    // here you can use the result of promiseB
});
215
задан Noctis 7 June 2014 в 11:57
поделиться

14 ответов

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

Если вам нужно сопоставить соответствующие вложенные скобки, тогда вам нужно нечто большее, чем регулярные выражения. - см. @dehmann

Если он просто открыт для последнего закрытия, см. @Zach

Решите, что вы хотите, чтобы :

abc ( 123 ( foobar ) def ) xyz ) ghij

Вам нужно решить, что ваш код должен соответствовать в этом случае.

114
ответ дан Community 22 August 2018 в 22:16
поделиться
  • 1
    скобка внутри класса не нуждается в экранировании. Поскольку внутри это не метахарактер. – José Leal 13 February 2009 в 16:59
  • 2
    Этот expr не подходит к чему-то вроде текстового (текстового) текста (текста) (текст) текста (текста) ". Регулярные выражения не могут считать скобки. – Christian Klauser 13 February 2009 в 17:02
  • 3
    Реализация .NET имеет [Определения балансировки группы msdn.microsoft.com/en-us/library/… , которые позволяют подобные вещи. – Carl G 13 June 2010 в 05:08
  • 4
    Я не согласен с тем, что регулярные выражения являются неправильным инструментом для этого по нескольким причинам. 1) Большинство реализаций регулярных выражений имеют для этого идеальное, если не идеальное решение. 2) Часто вы пытаетесь найти сбалансированные пары разделителей в контексте, в котором также находятся другие критерии, хорошо подходящие для регулярных выражений. 3) Часто вы передаете регулярное выражение в некоторый API, который принимает только регулярные выражения, и у вас нет выбора. – Kenneth Baltrinic 2 May 2014 в 04:31
  • 5
    Ниже приведен алгоритм Javascript алгоритма Фрэнка – pilau 23 November 2014 в 12:00
  • 6
    Это не ответ. – Alan Moore 23 November 2015 в 06:45
  • 7
    Да, требование об изменении вопроса должно быть дано в качестве комментария, – Gangnus 16 December 2015 в 11:32
  • 8
    Regex - это инструмент RIGHT для работы. Этот ответ неверен. См. Ответ rogal111. – Andrew 26 December 2015 в 03:48
  • 9
    Абсолютно согласен с ответом. Хотя в regexp есть некоторые реализации рекурсии, они равны конечно-государственным машинам и не поддерживают работу с вложенными структурами, но Context Free Grammars делают это. Посмотрите на иерархичность Хомского формальных грамматик. – Nick Roz 20 April 2016 в 10:52
115
ответ дан Community 5 November 2018 в 19:41
поделиться

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

Здесь вы можете прочитать хорошую статью здесь . Вам также может потребоваться прочитать регулярные выражения .NET. Вы можете начать читать здесь .

Были использованы угловые скобки <>, потому что они не требуют экранирования.

Регулярное выражение выглядит следующим образом:

<
[^<>]*
(
    (
        (?<Open><)
        [^<>]*
    )+
    (
        (?<Close-Open>>)
        [^<>]*
    )+
)*
(?(Open)(?!))
>
14
ответ дан Alan Moore 22 August 2018 в 22:16
поделиться
  • 1
    Что означает & quot; & lt; = & quot; и & quot; = & quot; Знаки означают? Что такое regexp engine - это таргетинг на выражение? – Christian Klauser 13 February 2009 в 16:58
  • 2
    Это внешний вид, или, вернее, «утверждения с нулевой шириной и вперед». Большинство современных двигателей с регулярным выражением поддерживают их. – Tomalak 13 February 2009 в 17:01
  • 3
  • 4
    @Alan M: Вы правы. Но в соответствии с текстом вопроса он хочет, чтобы все между находились самые внешние парнеры. Выберите свой выбор. Он сказал, что он пытался часами, поэтому даже не рассматривал «все, в том числе самые внешние парнеры». как намерение, потому что оно настолько тривиально: «(. *)». – Tomalak 15 February 2009 в 11:29
  • 5
    @ghayes Ответ от 2009 года. Это время long ; механизмы регулярного выражения, которые допускают некоторую рекурсию, были более необычными, чем сейчас (и они еще являются довольно необычными). Я расскажу об этом в своем ответе. – Tomalak 12 January 2015 в 08:54

Вы можете использовать рекурсию regex :

\(([^()]|(?R))*\)
69
ответ дан Amal Murali 22 August 2018 в 22:16
поделиться
  • 1
    Пример действительно был бы полезен здесь, я не могу заставить это работать на такие вещи, как «(1, (2, 3)) (4, 5)». – Andy Hayden 15 October 2014 в 01:01
  • 2
    @AndyHayden это потому, что "(1, (2, 3)) (4, 5)" имеет две группы, разделенные пробелом. Используйте мое регулярное выражение с глобальным флагом: / (([^ ()] | (? R)) *) / g. Вот онлайн-тест: regex101.com/r/lF0fI1/1 – rogal111 23 October 2014 в 10:45
  • 3
    – Andy Hayden 23 October 2014 в 18:20
  • 4
    В .NET 4.5 я получаю следующую ошибку для этого шаблона: Unrecognized grouping construct. – nam 28 June 2015 в 00:16
  • 5
    Потрясающие! Это отличная функция регулярного выражения. Спасибо, что вы единственный, кто действительно ответил на вопрос. Кроме того, сайт regex101 сладок. – Andrew 26 December 2015 в 03:47

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


.NET Regex с использованием балансировочных групп .

\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)

Где c используется как счетчик глубины.

Демонстрация в Regexstorm.com


PCRE с использованием рекурсивного шаблона .

\((?>[^)(]+|(?R))*+\)

Демонстрация в regex101 ; Или без чередования:

\((?>[^)(]*(?R)?)*+\)

Демо в regex101 ; Или разворачивается для исполнения:

\([^)(]*(?:(?R)[^)(]*)*+\)

Демонстрация в regex101 ; Рисунок наклеивается на (?R), который представляет (?0).

Perl, PHP, Notepad ++, R : perl = TRUE , Python : пакет Regex с (?V1) для поведения Perl.


Ruby с использованием вызовов подвыражения .

С Ruby 2.0 \g<0> можно использовать для вызова полного шаблона.

\((?>[^)(]+|\g<0>)*\)

Демоверсия в Rubular ; Ruby 1.9 поддерживает только рекурсию группы захвата группы :

(\((?>[^)(]+|\g<1>)*\))

Демо в Rubular & nbsp; ( атомная группировка с Ruby 1.9 .3)


JavaScript & nbsp; API :: XRegExp.matchRecursive

XRegExp.matchRecursive(str, '\\(', '\\)', 'g');

JS, Java и другие ароматы регулярных выражений без рекурсии до 2 уровня вложенности:

\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)

Демонстрация в regex101 . Более глубокое вложение нужно добавить к рисунку. Чтобы ускорить работу с несбалансированными скобками , снимите квантор +.


Java: интересная идея с использованием прямых ссылок by @jaytea .


Ссылка - Что означает это регулярное выражение?

60
ответ дан bobble bubble 22 August 2018 в 22:16
поделиться

Я написал небольшую библиотеку javascript, названную balanced , чтобы помочь с этой задачей, вы можете выполнить это, выполнив

balanced.matches({
    source: source,
    open: '(',
    close: ')'
});

, вы даже можете выполнять замены

balanced.replacements({
    source: source,
    open: '(',
    close: ')',
    replace: function (source, head, tail) {
        return head + source + tail;
    }
});

представляет собой более сложный и интерактивный пример JSFiddle

2
ответ дан Chad Scira 22 August 2018 в 22:16
поделиться

Это тоже работало

re.findall(r'\(.+\)', s)
0
ответ дан DataScienceStep 22 August 2018 в 22:16
поделиться
"""
Here is a simple python program showing how to use regular
expressions to write a paren-matching recursive parser.

This parser recognises items enclosed by parens, brackets,
braces and <> symbols, but is adaptable to any set of
open/close patterns.  This is where the re package greatly
assists in parsing. 
"""

import re


# The pattern below recognises a sequence consisting of:
#    1. Any characters not in the set of open/close strings.
#    2. One of the open/close strings.
#    3. The remainder of the string.
# 
# There is no reason the opening pattern can't be the
# same as the closing pattern, so quoted strings can
# be included.  However quotes are not ignored inside
# quotes.  More logic is needed for that....


pat = re.compile("""
    ( .*? )
    ( \( | \) | \[ | \] | \{ | \} | \< | \> |
                           \' | \" | BEGIN | END | $ )
    ( .* )
    """, re.X)

# The keys to the dictionary below are the opening strings,
# and the values are the corresponding closing strings.
# For example "(" is an opening string and ")" is its
# closing string.

matching = { "(" : ")",
             "[" : "]",
             "{" : "}",
             "<" : ">",
             '"' : '"',
             "'" : "'",
             "BEGIN" : "END" }

# The procedure below matches string s and returns a
# recursive list matching the nesting of the open/close
# patterns in s.

def matchnested(s, term=""):
    lst = []
    while True:
        m = pat.match(s)

        if m.group(1) != "":
            lst.append(m.group(1))

        if m.group(2) == term:
            return lst, m.group(3)

        if m.group(2) in matching:
            item, s = matchnested(m.group(3), matching[m.group(2)])
            lst.append(m.group(2))
            lst.append(item)
            lst.append(matching[m.group(2)])
        else:
            raise ValueError("After <<%s %s>> expected %s not %s" %
                             (lst, s, term, m.group(2)))

# Unit test.

if __name__ == "__main__":
    for s in ("simple string",
              """ "double quote" """,
              """ 'single quote' """,
              "one'two'three'four'five'six'seven",
              "one(two(three(four)five)six)seven",
              "one(two(three)four)five(six(seven)eight)nine",
              "one(two)three[four]five{six}seven<eight>nine",
              "one(two[three{four<five>six}seven]eight)nine",
              "oneBEGINtwo(threeBEGINfourENDfive)sixENDseven",
              "ERROR testing ((( mismatched ))] parens"):
        print "\ninput", s
        try:
            lst, s = matchnested(s)
            print "output", lst
        except ValueError as e:
            print str(e)
    print "done"
0
ответ дан Gene Olson 22 August 2018 в 22:16
поделиться

Это окончательное регулярное выражение:

\(
(?<arguments> 
(  
  ([^\(\)']*) |  
  (\([^\(\)']*\)) |
  '(.*?)'

)*
)
\)

Пример:

input: ( arg1, arg2, arg3, (arg4), '(pip' )

output: arg1, arg2, arg3, (arg4), '(pip'

обратите внимание, что '(pip' правильно управляется как строка. (проверено в регуляторе: http://sourceforge.net/projects/regulator/ )

3
ответ дан Marco 22 August 2018 в 22:16
поделиться

Регулярное выражение с использованием Ruby (версия 1.9.3 или выше):

/(?<match>\((?:\g<match>|[^()]++)*\))/

Демо на rubular

2
ответ дан nhahtdh 22 August 2018 в 22:16
поделиться

, так что вам нужна первая и последняя родительская головка, используйте smth, как этот str.indexOf ('('); - он даст вам первое появление str.lastIndexOf (')'); - last one

, так что вам нужна строка между, String searchString = str.substring (str1.indexOf ('('), str1.lastIndexOf (')');

1
ответ дан Shell Scott 22 August 2018 в 22:16
поделиться

Этот ответ объясняет теоретическое ограничение того, почему регулярные выражения не являются подходящим инструментом для этой задачи.


Регулярные выражения не могут этого сделать.

Регулярные выражения основаны на вычислительной модели, известной как Finite State Automata (FSA). Как видно из названия, FSA может помнить только текущее состояние, оно не имеет информации о предыдущих состояниях.

На приведенной выше диаграмме , S1 и S2 - это два состояния, где S1 является начальным и конечным шагами. Поэтому, если мы попробуем со строкой 0110, переход будет выглядеть следующим образом:

      0     1     1     0
-> S1 -> S2 -> S2 -> S2 ->S1

В вышеприведенных шагах, когда мы находимся на втором S2, т.е. после разбора 01 в 0110 , FSA не имеет информации о предыдущем 0 в 01, так как он может только помнить текущее состояние и следующий входной символ.

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

Однако для достижения цели можно написать алгоритм. Алгоритмы обычно подпадают под Pushdown Automata (PDA). PDA на один уровень выше FSA. У КПК есть дополнительный стек, чтобы что-то хранить. КПК могут использоваться для решения вышеуказанной проблемы, потому что мы можем «push» открывать скобки в стеке и «pop» их, как только мы сталкиваемся с закрывающей скобкой. Если в конце стопка пуста, откроются скобки и закрывающая скобка. В противном случае нет.

Подробное обсуждение можно найти здесь здесь .

4
ответ дан Somnath Musib 22 August 2018 в 22:16
поделиться

Это настраиваемое решение, позволяющее использовать одиночные символьные литеральные разделители в Java:

public static List<String> getBalancedSubstrings(String s, Character markStart, 
                                 Character markEnd, Boolean includeMarkers) 

{
        List<String> subTreeList = new ArrayList<String>();
        int level = 0;
        int lastOpenDelimiter = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == markStart) {
                level++;
                if (level == 1) {
                    lastOpenDelimiter = (includeMarkers ? i : i + 1);
                }
            }
            else if (c == markEnd) {
                if (level == 1) {
                    subTreeList.add(s.substring(lastOpenDelimiter, (includeMarkers ? i + 1 : i)));
                }
                if (level > 0) level--;
            }
        }
        return subTreeList;
    }
}

Использование образца:

String s = "some text(text here(possible text)text(possible text(more text)))end text";
List<String> balanced = getBalancedSubstrings(s, '(', ')', true);
System.out.println("Balanced substrings:\n" + balanced);
// => [(text here(possible text)text(possible text(more text)))]
1
ответ дан Wiktor Stribiżew 22 August 2018 в 22:16
поделиться
14
ответ дан Alan Moore 5 November 2018 в 19:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: