onInputMove
не является методом обратного вызова. Поэтому вам нужно сделать что-то вроде:
var event = function (ev) {self.onInputMove (ev)}; someDom.addEventListener ('mousemove', event, false); someDom.removeEventListener ('mousemove', event, false);
Регулярное выражение пытается сопоставить как можно больше текста, тем самым потребляя всю вашу строку. Он не ищет дополнительных совпадений регулярного выражения в частях этой строки. Вот почему вы получаете только один ответ.
Решение состоит в том, чтобы не использовать регулярные выражения. Если вы на самом деле пытаетесь разобрать математические выражения, используйте реальные решения синтаксического анализа. Если вы действительно хотите захватить фигуры в круглых скобках, просто зациклируйте символы, подсчитывая, когда вы видите (и), и увеличиваете декремент счетчика.
Вы должны написать правильный синтаксический анализатор для синтаксического анализа такого выражения (например, с помощью pyparsing). Регулярные выражения не являются подходящим инструментом для написания достойных парсеров.
Стек - лучший инструмент для задания: -
import re
def matches(line, opendelim='(', closedelim=')'):
stack = []
for m in re.finditer(r'[{}{}]'.format(opendelim, closedelim), line):
pos = m.start()
if line[pos-1] == '\\':
# skip escape sequence
continue
c = line[pos]
if c == opendelim:
stack.append(pos+1)
elif c == closedelim:
if len(stack) > 0:
prevpos = stack.pop()
# print("matched", prevpos, pos, line[prevpos:pos])
yield (prevpos, pos, len(stack))
else:
# error
print("encountered extraneous closing quote at pos {}: '{}'".format(pos, line[pos:] ))
pass
if len(stack) > 0:
for pos in stack:
print("expecting closing quote to match open quote starting at: '{}'"
.format(line[pos-1:]))
В клиентском коде, поскольку функция записывается как функция генератора, просто используйте шаблон for loop для разворачивания совпадений: -
line = '(((1+0)+1)+1)'
for openpos, closepos, level in matches(line):
print(line[openpos:closepos], level)
Этот тестовый код выводит следующий на моем экране, заметил, что второй параметр в распечатке указывает глубину в скобках.
1+0 2
(1+0)+1 1
((1+0)+1)+1 0
Вот демо для вашего вопроса, хотя оно неуклюжие, пока оно работает
import re s = '(((1+0)+1)+1)'
def getContectWithinBraces( x , *args , **kwargs):
ptn = r'[%(left)s]([^%(left)s%(right)s]*)[%(right)s]' %kwargs
Res = []
res = re.findall(ptn , x)
while res != []:
Res = Res + res
xx = x.replace('(%s)' %Res[-1] , '%s')
res = re.findall(ptn, xx)
print(res)
if res != []:
res[0] = res[0] %('(%s)' %Res[-1])
return Res
getContectWithinBraces(s , left='\(\[\{' , right = '\)\]\}')
Языки регексов недостаточно эффективны для сопоставления произвольно вложенных конструкций. Для этого вам нужен пусковой автомат (т. Е. Синтаксический анализатор). Доступно несколько таких инструментов, таких как PLY .
Python также предоставляет библиотеку синтаксиса для своего собственного синтаксиса, который может делать то, что вам нужно. Выход очень подробный, однако, и занимает некоторое время, чтобы обернуть голову. Если вы заинтересованы в этом угле, следующее обсуждение пытается объяснить все как можно проще.
>>> import parser, pprint
>>> pprint.pprint(parser.st2list(parser.expr('(((1+0)+1)+1)')))
[258,
[327,
[304,
[305,
[306,
[307,
[308,
[310,
[311,
[312,
[313,
[314,
[315,
[316,
[317,
[318,
[7, '('],
[320,
[304,
[305,
[306,
[307,
[308,
[310,
[311,
[312,
[313,
[314,
[315,
[316,
[317,
[318,
[7, '('],
[320,
[304,
[305,
[306,
[307,
[308,
[310,
[311,
[312,
[313,
[314,
[315,
[316,
[317,
[318,
[7,
'('],
[320,
[304,
[305,
[306,
[307,
[308,
[310,
[311,
[312,
[313,
[314,
[315,
[316,
[317,
[318,
[2,
'1']]]]],
[14,
'+'],
[315,
[316,
[317,
[318,
[2,
'0']]]]]]]]]]]]]]]],
[8,
')']]]]],
[14,
'+'],
[315,
[316,
[317,
[318,
[2,
'1']]]]]]]]]]]]]]]],
[8, ')']]]]],
[14, '+'],
[315,
[316,
[317,
[318, [2, '1']]]]]]]]]]]]]]]],
[8, ')']]]]]]]]]]]]]]]],
[4, ''],
[0, '']]
Вы можете облегчить боль этой короткой функцией:
def shallow(ast):
if not isinstance(ast, list): return ast
if len(ast) == 2: return shallow(ast[1])
return [ast[0]] + [shallow(a) for a in ast[1:]]
>>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)'))))
[258,
[318,
'(',
[314,
[318, '(', [314, [318, '(', [314, '1', '+', '0'], ')'], '+', '1'], ')'],
'+',
'1'],
')'],
'',
'']
Числа поступают из модулей Python symbol
и token
, которые вы можете использовать для построения таблицы поиска из чисел в имена:
map = dict(token.tok_name.items() + symbol.sym_name.items())
Вы даже можете свернуть это сопоставление в shallow()
, чтобы вы могли работать со строками вместо чисел:
def shallow(ast):
if not isinstance(ast, list): return ast
if len(ast) == 2: return shallow(ast[1])
return [map[ast[0]]] + [shallow(a) for a in ast[1:]]
>>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)'))))
['eval_input',
['atom',
'(',
['arith_expr',
['atom',
'(',
['arith_expr',
['atom', '(', ['arith_expr', '1', '+', '0'], ')'],
'+',
'1'],
')'],
'+',
'1'],
')'],
'',
'']
Я считаю, что эта функция может удовлетворить вашу потребность, я быстро выбросил ее, поэтому не стесняйтесь немного ее очистить. При выполнении гнезд легко думать об этом назад и работать оттуда =]
def fn(string,endparens=False):
exp = []
idx = -1
for char in string:
if char == "(":
idx += 1
exp.append("")
elif char == ")":
idx -= 1
if idx != -1:
exp[idx] = "(" + exp[idx+1] + ")"
else:
exp[idx] += char
if endparens:
exp = ["("+val+")" for val in exp]
return exp
Существует новый регулярный модуль двигателя , готовый заменить существующий в Python. Он вводит много новых функций, включая рекурсивные вызовы.
import regex
s = 'aaa(((1+0)+1)+1)bbb'
result = regex.search(r'''
(?<rec> #capturing group rec
\( #open parenthesis
(?: #non-capturing group
[^()]++ #anyting but parenthesis one or more times without backtracking
| #or
(?&rec) #recursive substitute of group rec
)*
\) #close parenthesis
)
''',s,flags=regex.VERBOSE)
print(result.captures('rec'))
Выход:
['(1+0)', '((1+0)+1)', '(((1+0)+1)+1)']
Связанная ошибка в regex
: http: // код. google.com/p/mrab-regex-hg/issues/detail?id=78
Сбалансированные пары (например, круглые скобки) являются примером языка, который не может быть распознан регулярными выражениями.
Далее следует краткое объяснение математики, почему это так.
Регулярные выражения - это способ определения автоматов с конечным состоянием (сокращенный FSM). Такое устройство имеет конечное количество возможного состояния для хранения информации. То, как это состояние может быть использовано, конкретно не ограничено, но это означает, что существует абсолютное максимальное количество различных позиций, которые он может распознать.
Например, состояние может использоваться для подсчета, скажем, несогласованных левых скобок. Но поскольку количество состояний для такого подсчета должно быть полностью ограничено, то данный FSM может рассчитывать до максимума n -1, где n - это число указывает, что FSM может быть в. Если n , скажем, 10, то максимальное количество несогласованных левых скобок FSM может совпадать, равно 10, пока оно не сломается. Поскольку вполне возможно иметь еще одну левую скобку, нет возможности FSM, который может правильно распознать полный язык совпадающих круглых скобок.
Ну и что? Предположим, вы просто выбрали действительно большой n ? Проблема в том, что в качестве способа описания FSM регулярные выражения в основном описывают все переходы из одного состояния в другое. Так как для любого N для FSM потребуется 2 перехода состояния (одно для сопоставления левой скобки и одно для правильного совпадения), само регулярное выражение должно расти, по крайней мере, с постоянным множителем, кратным n
. Для сравнения, следующий лучший класс языков (контекстно-свободные грамматики) может решить эту проблему совершенно компактным образом. Вот пример в BNF
expression ::= `(` expression `)` expression
| nothing
blockquote>
L = { ww | w \in {0,1}* }
, который не является ни регулярным, ни контекстным. Верно, что они не могут соответствовать произвольно вложенным совпадающим скобкам, но не по той причине, о которой вы говорили.
– phooji
28 March 2011 в 05:15
Из связанного ответа:
Из утилиты LilyPond convert-ly (и написана / защищена авторским правом, поэтому я могу показать ее здесь):
def paren_matcher (n):
# poor man's matched paren scanning, gives up
# after n+1 levels. Matches any string with balanced
# parens inside; add the outer parens yourself if needed.
# Nongreedy.
return r"[^()]*?(?:\("*n+r"[^()]*?"+r"\)[^()]*?)*?"*n
convert -ly имеет тенденцию использовать это как paren_matcher (25) в своих регулярных выражениях, которые, вероятно, будут излишними для большинства приложений. Но затем он использует его для сопоставления выражений Схемы.
Да, он ломается после заданного предела, но способность просто подключать его к регулярным выражениям по-прежнему превосходит «правильные» альтернативы, поддерживающие неограниченную глубину рук в удобстве использования.