2015-10-14 3 views
2

Я изучаю регулярные выражения, поэтому извиняюсь за простой вопрос.regex - как выбрать слово, в котором есть '-'?

Я хочу, чтобы выбрать слова, которые имеют «-» (минус) в нем, но не в начале и не в конце слова

Я попытался (с помощью FindAll):

r'\b-\b' 

для

str = 'word semi-column peace' 

, но, конечно, есть только:

['-'] 

Спасибо!

+0

Я хорошее место, чтобы проверить регулярное выражение в реальных без необходимости запуска кода является http://pythex.org/ – reticentroot

ответ

3

а '-' (минус) в нем, но не в начале и не в конце слова

Поскольку "-" является не слово символ, вы не можете использовать границы слов (\b), чтобы предотвратить совпадение слов с дефисами в начале или в конце. Строка типа "-not-wanted-" будет соответствовать как \b\w+-\w+\b, так и \w+-\w+.


Нам нужно добавить дополнительное условие до и после слова:

  • Перед: (?<![-\w]) не предшествует ни дефисом, ни слова характера.
  • После: (?![-\w]) не следует ни дефисом, ни символом слова.

Кроме того, в нем может быть более 1 дефиса, и мы должны разрешить это.Что мы можем сделать здесь повторить последнюю часть слова («дефис и слова символы») один раз или больше:

  • \w+(?:-\w+)+ матчи:
    • \w+ один или несколько слов символов
    • (?:-\w+)+ дефис и один или несколько символов слова, а также позволяет повторить эту последнюю часть.

Regex:

(?<![-\w])\w+(?:-\w+)+(?![-\w]) 

regex101 demo

Код:

import re 

pattern = re.compile(r'(?<![-\w])\w+(?:-\w+)+(?![-\w])') 
text = "-abc word semi-column peace -not-wanted- one-word dont-match- multi-hyphenated-word" 

result = re.findall(pattern, text) 

ideone demo

+0

очень всеобъемлющий! – Toly

+0

Как любое регулярное выражение должно быть :) – Mariano

+0

Что произойдет, если есть выражение? Например, вместо «semi-column» будет «2.0-3-альфа», это будет работать (это будет игнорировать выражение)? – Toly

4
str is a built in name, better not to use it for naming 

st = 'word semi-column peace' 
# \w+ word - \w+ word after - 
print(re.findall(r"\b\w+-\w+\b",st)) 

['semi-column'] 
+3

объяснение всегда приветствуется :) –

+0

@LetzerWilie - Спасибо! Что делать, если вместо слов есть выражение: «2.2 -3.5-бета»? Будет ли это работать (а это означает, что регулярное выражение будет игнорировать выражение)? Также определение слов (из того, что я собрал) может немного изменить одну реализацию регулярного выражения на другую. Есть ли способ решить это? – Toly

4

То, что вы на самом деле хотите сделать это регулярное выражение, как это:

\w+-\w+ 

Что это означает найти алфавитно-цифровой символ, по крайней мере один раз, как указано в использовании «+», то найти '-', следуя другим алфавитно-цифровым символом, по крайней мере, один раз, снова, как показано символом «+» снова.

+0

Спасибо! большое объяснение! – Toly

+0

Добро пожаловать! – idjaw

0

Вы можете попробовать что-то вроде этого: центрируя дефис, я совпадаю до тех пор, пока в дефис не будет пробела в любом направлении. Я также делаю чек, чтобы увидеть, окружены ли слова дефисами (например, -test-cats-), и если они, то я не буду их включать. Регулярное выражение также должно работать с findall.

st = 'word semi-column peace' 
m = re.search(r'([^ | ^-]+-[^ | ^-]+)', st) 
if m: 
    print m.group(1) 
+0

другой креативный подход! Спасибо вам всем! – Toly

1

Вы также можете использовать следующее регулярное выражение:

>>> st = "word semi-column peace" 
>>> print re.findall(r"\S+\-\S+", st) 
['semi-column'] 
Смежные вопросы