promiseA
then
возвращает новое обещание (promiseB
), которое немедленно разрешается после разрешения promiseA
, его значение является значением того, что возвращается из функции успеха в promiseA
.
В этом случае promiseA
разрешается со значением - result
, а затем немедленно разрешает promiseB
со значением result + 1
.
Доступ к значению promiseB
выполняется так же, как мы получили доступ к результату promiseA
.
promiseB.then(function(result) {
// here you can use the result of promiseB
});
Ответ зависит от того, нужно ли вам сопоставлять совпадающие наборы скобок или просто сначала открыть последнее закрытие входного текста.
Если вам нужно сопоставить соответствующие вложенные скобки, тогда вам нужно нечто большее, чем регулярные выражения. - см. @dehmann
Если он просто открыт для последнего закрытия, см. @Zach
Решите, что вы хотите, чтобы :
abc ( 123 ( foobar ) def ) xyz ) ghij
Вам нужно решить, что ваш код должен соответствовать в этом случае.
На самом деле это можно сделать с помощью регулярных выражений .NET, но это не так, но читайте внимательно.
Здесь вы можете прочитать хорошую статью здесь . Вам также может потребоваться прочитать регулярные выражения .NET. Вы можете начать читать здесь .
Были использованы угловые скобки <>
, потому что они не требуют экранирования.
Регулярное выражение выглядит следующим образом:
<
[^<>]*
(
(
(?<Open><)
[^<>]*
)+
(
(?<Close-Open>>)
[^<>]*
)+
)*
(?(Open)(?!))
>
Вы можете использовать рекурсию regex :
\(([^()]|(?R))*\)
Unrecognized grouping construct
.
– nam
28 June 2015 в 00:16
Я хочу добавить этот ответ для быстрой ссылки. Невозможно обновить.
.NET Regex с использованием балансировочных групп .
\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)
Где c
используется как счетчик глубины.
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 .
Я написал небольшую библиотеку javascript, названную balanced , чтобы помочь с этой задачей, вы можете выполнить это, выполнив
balanced.matches({
source: source,
open: '(',
close: ')'
});
, вы даже можете выполнять замены
balanced.replacements({
source: source,
open: '(',
close: ')',
replace: function (source, head, tail) {
return head + source + tail;
}
});
представляет собой более сложный и интерактивный пример JSFiddle
Это тоже работало
re.findall(r'\(.+\)', s)
"""
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"
Это окончательное регулярное выражение:
\(
(?<arguments>
(
([^\(\)']*) |
(\([^\(\)']*\)) |
'(.*?)'
)*
)
\)
Пример:
input: ( arg1, arg2, arg3, (arg4), '(pip' )
output: arg1, arg2, arg3, (arg4), '(pip'
обратите внимание, что '(pip'
правильно управляется как строка. (проверено в регуляторе: http://sourceforge.net/projects/regulator/ )
Регулярное выражение с использованием Ruby (версия 1.9.3 или выше):
/(?<match>\((?:\g<match>|[^()]++)*\))/
, так что вам нужна первая и последняя родительская головка, используйте smth, как этот str.indexOf ('('); - он даст вам первое появление str.lastIndexOf (')'); - last one
, так что вам нужна строка между, String searchString = str.substring (str1.indexOf ('('), str1.lastIndexOf (')');
Этот ответ объясняет теоретическое ограничение того, почему регулярные выражения не являются подходящим инструментом для этой задачи.
Регулярные выражения не могут этого сделать.
Регулярные выражения основаны на вычислительной модели, известной как 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
» их, как только мы сталкиваемся с закрывающей скобкой. Если в конце стопка пуста, откроются скобки и закрывающая скобка. В противном случае нет.
Подробное обсуждение можно найти здесь здесь .
Это настраиваемое решение, позволяющее использовать одиночные символьные литеральные разделители в 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)))]