2010-06-28 6 views
4

Это вопрос с участием условное регулярное выражение в Python:Python Условный Regular Expression

Я хотел бы, чтобы соответствовать строке "abc" с

match(1)="a" 
match(2)="b" 
match(3)="c" 

, но и соответствовать строке " a" с

match(1)="a" 
match(2)="" 
match(3)="" 

Следующий код ALMOST делает это, проблема в том, что в первом случае match(1)="a" bu t во втором случае, match(4)="a" (не match(1) по желанию).

Фактически, если вы перебираете все группы с помощью for g in re.search(myre,teststring2).groups():, вы получаете 6 групп (не 3, как ожидалось).

import re 
import sys 

teststring1 = "abc" 
teststring2 = " a" 

myre = '^(?=(\w)(\w)(\w))|(?=\s{2}(\w)()())' 

if re.search(myre,teststring1): 
    print re.search(myre,teststring1).group(1) 

if re.search(myre,teststring2): 
    print re.search(myre,teststring2).group(1) 

Любые мысли? (Обратите внимание, это на Python 2.5)

ответ

5

Может быть ...:

import re 
import sys 

teststring1 = "abc" 
teststring2 = " a" 

myre = '^\s{0,2}(\w)(\w?)(\w?)$' 

if re.search(myre,teststring1): 
    print re.search(myre,teststring1).group(1) 

if re.search(myre,teststring2): 
    print re.search(myre,teststring2).group(1) 

Это даст a в обоих случаях, как вы хотите, но, возможно, это не будет соответствовать, как вы хотите в других случаях вы не показывать (например, без пробелов впереди или пробелы и более одной буквы, так что общая длина строки соответствует != 3 ... но я просто догадываюсь, что вы не хотите совпадения в таких случаях ...?)

+0

Вы правы - это единственные два случая. Работает так, как я надеялся. Ключ имел «?» внутри группы соответствия (\ w?), чтобы либо она соответствовала букве, либо ничего не соответствовала. Благодаря! – Mike

+0

@Mike, добро пожаловать - всегда рад помочь! –

1
myre = '^(?=\s{0,2}(\w)(?:(\w)(\w))?)' 

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

Общее решение очень сложно найти, потому что обработка последующих элементов зависит от обработки предыдущих и/или наоборот. Например, начальные пробелы не должны быть там, если у вас есть полный abc. И если начальные пробелы есть, вы должны найти только a.

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

Правило для групп состоит в том, что все открытые круглые скобки, за которыми сразу не следует ?:, становятся группой. Эта группа может быть пуста, поскольку она фактически не соответствует чему-либо, но она будет там.

3

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

r = re.compile("^\s*(\w)(\w)?(\w)?$") 

abc -> ('a', 'b', 'c') 
a -> ('a', None, None) 

Чтобы разбить его:

^  // anchored at the beginning 
\s* // Any number of spaces to start with 
(\w) // capture the first letter, which is required 
(\w)? // capture the second letter, which is optional 
(\w)? // capture the third letter, which is optional 
$  // anchored at the end