Python заменить неопределенную длину текста - PullRequest
2 голосов
/ 01 марта 2012

У меня есть такая строка:

Hi. My name is _John_. I am _20_ years old.

и я хотел бы преобразовать это в это:

Hi. My name is <b>John</b>. I am <b>20</b> years old.

Я сделал что-то подобное, но не повезло.

import re
text = "Hi. My name is _John_. I am _20_ years old."
pattern = "(.*)(\_)(.*)(\_)(.*)"
re.sub(pattern, r'\1<b>\3</b>\5', text)
'Hi. My name is _John_. I am <b>20</b> years old.'

Что не так с рисунком? Почему он не видит первый жирный текст?

Любая помощь будет оценена. Спасибо.

Ответы [ 6 ]

4 голосов
/ 01 марта 2012

Изменить на:

pattern = "_([^_]*)_"
re.sub(pattern, r'<b>\1</b>', text)

Также см. этот пример .

4 голосов
/ 01 марта 2012

Проблема в том, что * является жадным и потребляет столько символов, сколько возможно (включая больше _). Чтобы исправить это, вы можете использовать не жадную альтернативу *? следующим образом:

>>> pattern = r'_(.*?)_'
>>> replacement = r'<b>\1</b>'
>>> re.sub(pattern ,replacement, text)
'Hi. My name is <b>John</b>. I am <b>20</b> years old.'

Обратите внимание, что re.sub ведет себя как re.search вместо re.match. То есть, вы можете использовать шаблон, который только частично соответствует вводу (в данном случае, просто некоторый текст, окруженный _) вместо того, что соответствует всей строке.

3 голосов
/ 01 марта 2012

Вы пробовали использовать Строковые шаблоны ?Они были построены для чего-то вроде этого.Простые строковые замены.Чертовски чище и элегантнее, чем использование регулярных выражений ...

import string

new_style = string.Template('Hi. My name is $name. I am $age years old.')
print new_style % {'name':'<b>John</b>', 'age':'<b>20</b>'} #produces what u want.

Чтобы узнать больше о примерах шаблонов строк, проверьте эту ссылку activeState

3 голосов
/ 01 марта 2012

Проблема в том, что ваши первые .* в шаблоне съедают все слева от последнего возможного совпадения. Поэтому говорят, что * является жадным . Используйте не жадный шаблон

pattern='_(.+?)_'
re.sub(pattern, r'<b>\1</b>', text)

? делает совпадение нежадным ; как можно короче. + требуется на востоке один символ между двумя подчеркиваниями, чтобы его можно было заменить на <b>text</b>. Так что __ останется __

Если вы хотите, чтобы __ стал <b></b>, используйте .*?

2 голосов
/ 01 марта 2012

Это потому, что шаблон жадный , а первый (.*) соответствует тексту от начала до третьего _:

>>> re.match(pattern, text).groups()
('Hi. My name is _John_. I am ', '_', '20', '_', ' years old.')

Вот упрощенная, не жадная версия:

>>> re.sub('_(.+?)_', r'<b>\1</b>', text)
'Hi. My name is <b>John</b>. I am <b>20</b> years old.'
1 голос
/ 01 марта 2012

Это звучит замечательно, как синтаксис уценки , поэтому, если ваша цель состоит в том, чтобы разобрать это, уже существует библиотека питонов .

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