2016-05-08 4 views
2

Я занимаюсь довольно простым регулярным выражением на питоне и вижу некоторое нечетное поведение, когда я использую оператор «или».Python регулярное выражение между символами

Я пытаюсь разобрать следующее:

>> str = "blah [in brackets] stuff" 

так, что она возвращает:

>> ['blah', 'in brackets', 'stuff'] 

Чтобы соответствовать тексту в квадратных скобках, я использую вид сзади и смотреть вперед, то есть:

>> '(?<=\[).*?(?=\])' 

Если используется один, это действительно фиксирует текст в скобках:

>> re.findall('(?<=\[).*?(?=\])' , str) 
>> ['in brackets'] 

Но когда я объединить или оператора для разбора строк между пространствами, скобка-матч как-то ломается:

>> [x for x in re.findall('(?<=\[).*?(?=\])|.*?[, ]' , str) if x!=' ' ] 
>> ['blah', '[in ', 'brackets] '] 

Для жизни меня я не могу понять это поведение. Любая помощь будет оценена по достоинству.

Спасибо!

+1

Это может помочь - https://regex101.com/r/xM7sK0/1 - на левой стороне вы можете перейти в отладчик, где он будет объяснить, как он соответствовал тому, что он делал. – TessellatingHeckler

+0

Спасибо, это действительно полезно. – FrancisWolcott

+0

Проблема в том, что вторая половина регулярного выражения также соответствует скобкам. После первого совпадения («бла») оставшийся текст «[в скобках]». Первая половина регулярного выражения здесь не соответствует, потому что lookbehind не находит открывающую скобку. Итак, вторая половина регулярного выражения снова совпадает и находит текст «[in». –

ответ

2

Вы можете сделать:

>>> s = "blah [in brackets] stuff" 

>>> re.findall(r'\b\w+\s*\w+\b', s) 
['blah', 'in brackets', 'stuff'] 
+0

Спасибо! Это хорошее решение. Мне все еще интересно понять, почему моя работа не работает. Пройдя через нее в голове, это имеет смысл: попытайтесь сопоставить то, что находится между скобками, если нет, сопоставить все, что предшествует пробелу. Для меня не имеет смысла, что введение оператора или оператора нарушает скобку. Есть идеи? – FrancisWolcott

0

Если вы ищете простой способ сделать это, а затем использовать это. Примечание: Я заменил str на строку, поскольку 'str' является встроенной функцией python.

import re 
string = "blah [in brackets] stuff" 
f = re.findall(r'\w+\w', string) 
print(f) 

Выход: [ «бла», «в скобках», «вещи»]

0

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

s = "blah [in brackets] stuff" 

s = re.split(r'\s*\[|\]\s*', s) # note the 'or' operator is used and literal opening and closing brackets '\[' and '\]' 

print(s) 

выход: ['blah', 'in brackets', 'stuff']

И пример с использованием строки с различными количествами слов внутри скобок и использование нескольких комплектов кронштейнов:

s = "blah [in brackets] stuff [three words here] more stuff [one-word] stuff [a digit 1!] stuff." 

s = re.split(r'\s*\[|\]\s*', s) 

print (s) 

выход: ['blah', 'in brackets', 'stuff', 'three words here', 'more stuff', 'one-word', 'stuff', 'a digit 1!', 'stuff.']

+0

Мне очень нравится ваше решение. Также легко включать другие разделители, помещая их в группу с скобками. Единственное, что состоит в том, что он не разбивает несколько слов вне скобок, т. Е. Возвращает «больше материала» вместо ['more', 'stuff']. – FrancisWolcott

2

Для тех, интересно, это успешное регулярное выражение, с которым я столкнулся. Существует, вероятно, более элегантное решение где-нибудь, но это работает:

>>> s = "blah 2.0 stuff 1 1 0 [in brackets] more stuff [1]" 

>>> brackets_re = '(?<=\[).*?(?=\])' 
>>> space_re = '[-\.\w]+(?=)' 
>>> my_re = brackets_re + '|' + space_re 

>>> re.findall(my_re, s) 
['blah', '2.0', 'stuff', '1', '1', '0', 'in brackets', 'more', 'stuff', '1'] 
+0

Красиво сделано Фрэнсис –

Смежные вопросы