2009-09-10 2 views
18

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

... 
VALUE 100 234 568 9233 119 
... 
VALUE 101 124 9223 4329 1559 
... 

Я хотел бы, чтобы захватить список номеров, что происходит после первого падения линии, которая начинается с VALUE. т. е. я хочу, чтобы он возвращал ('100','234','568','9233','119'). Проблема в том, что я заранее не знаю, сколько будет номеров.

Я попытался использовать это как регулярное выражение:

VALUE (?:(\d+)\s)+ 

Это соответствует линии, но он только фиксирует последнее значение, так что я просто получить («119»,).

+1

Основываясь на предыдущем вопросе, я вижу, что это невозможно с регулярными выражениями: http://stackoverflow.com/questions/464736/python-regular-expressions-how-to-capture-multiple-groups-from-a -wildcard-expre # 464755 –

ответ

16

То, что вы ищете, является парсером , вместо регулярного выражения. В вашем случае, я бы рассмотреть возможность использования очень простой парсера, split():

s = "VALUE 100 234 568 9233 119" 
a = s.split() 
if a[0] == "VALUE": 
    print [int(x) for x in a[1:]] 

Вы можете использовать регулярные выражения, чтобы увидеть, соответствует ли вашей входной строке планируемого формата (с использованием регулярных выражений в вашем вопросе), то вы можете выполните вышеуказанный код без необходимости проверки на "VALUE" и зная, что преобразование int(x) всегда будет успешным, так как вы уже подтвердили, что следующие группы символов являются цифрами.

2

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

matches = Regex.Match(log) 

foreach (Match match in matches) 
{ 
    submatches = Regex2.Match(match) 
} 

Это, конечно же, если вы не хотите, чтобы написать полный синтаксический анализатор ,

+2

Какой язык программирования? –

9
>>> import re 
>>> reg = re.compile('\d+') 
>>> reg.findall('VALUE 100 234 568 9233 119') 
['100', '234', '568', '9223', '119'] 

Это не подтверждает, что ключевое слово «VALUE» появляется в начале строки, и это не подтверждает, что существует ровно один пробел между элементами, но если вы можете сделать это в качестве отдельного (или если вам вообще этого не нужно), тогда он найдет все последовательности цифр в любой строке.

2

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

VALUE *(\d+)? *(\d+)? *(\d+)? *(\d+)? *(\d+)? *$ 

Это регулярное выражение захватывает до 5-значных групп, разделенных пробелами. Если вам нужно больше потенциальных групп, просто скопируйте и вставьте больше *(\d+)? блоков.

0

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

VALUE((\s\d+)+) 

Это должно привести в трех матчах: [0] вся линия, [1] материал после значения [2] последнего пространства + значения.

[0] и [2] могут быть проигнорированы, а затем [1] может быть использован со следующим:

\s(\d+) 

Примечание: эти регэкспы не были проверены, я надеюсь, что вы получите эту идею, хотя.


Причина Greg's answer не работает для меня потому, что вторая часть синтаксического анализа является более сложным, а не просто некоторые числа, разделенных пробелом.

Однако я бы честно пошел с решением Грега по этому вопросу (это, вероятно, более эффективно).

Я просто пишу этот ответ, если кто-то ищет более сложное решение, как мне было нужно.