Если вы действительно хороши в Python и Regex, пожалуйста, помогите исправить функцию - PullRequest
1 голос
/ 20 февраля 2010
def boldword(text, needle):
    return mark_safe(re.compile(r"\b(%s)\b" % "|".join(map(re.escape, needle.split(' '))), re.I).sub(r'<strong>\1</strong>', text))

Это моя функция выделять текст строки с помощью иглы. (Как Google ... они выделяют текст для вас, когда вы делаете поиск).

  • Если стрелка «шоу», она не будет выделять «www. theshow .com».
  • Когда стрелка «мое шоу (видео)», она не будет выделять « мое шоу (видео) » ... она только выделяет мое шоу .
  • Когда стрелка - «яблочный iPad», она не будет выделять «яблочный iPad» ... она только подсвечивает iPad.

    Ожидаемый результат: WWW. theshow .com Токовый выход: www.theshow.com

    Ожидаемый результат: мое шоу (видео) Токовый выход: мое шоу (видео)

    Ожидаемое: apple ipad ,Текущий: яблоко ipad

Я думаю, что главная проблема в том, что я делю пробел и другие знаки препинания. право? Может ли кто-нибудь изменить мою текущую функцию, чтобы учесть эти факторы?

Спасибо

Ответы [ 3 ]

2 голосов
/ 20 февраля 2010

Ваша самая большая проблема, кажется, границы слова. Если искомые токены могут начинаться или заканчиваться несловарными символами (например, (video)), включение регулярного выражения в \b предотвращает сопоставление. Они также предотвращают сопоставление двух или более смежных токенов (например, theshow в www.theshow.com). Однако вместо того, чтобы терять границы слов, я предлагаю вам игнорировать знаки препинания в поисковом выражении и составить регулярное выражение, чтобы соответствовать одному или нескольким токенам за раз:

re.compile(r"\b((?:%s)+)\b" % "|".join(re.split(r"\W+", needle)), re.I)

Разделение на /\W+/ удаляет все знаки пунктуации и пробелы, поэтому не нужно ничего избегать. Похоже, мои результаты совпадают с теми, которые вы хотели, за исключением того, что скобки в (video) не выделены, только слово video. Если поисковое выражение "the show", оно выделяет theshow в www.theshow.com, но не в www.footheshowbar.com.

1 голос
/ 20 февраля 2010

Вот некоторая клейкая лента, которую я добавил, чтобы помочь вам пройти перечисленные случаи - эта проблема на самом деле довольно интересная. Вероятно, есть некоторые случаи, которые не будут корректными (например, Google выделит duck, если вы ищете ducks, это будет работать только для duck's).

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

import re, string

def boldword(text,needle):
    n = re.sub('[%s]s*' % re.escape(string.punctuation), '', needle)
    patterns = map(re.escape, n.split(' '))
    patterns.append(n.replace(' ', ''))
    regex = re.compile(r"\b(%s)\b" % '|'.join(patterns), re.I)
    match = re.match(regex, text.replace(' ',''))
    if match:
        return "<strong>%s</strong>" % text
    return re.sub(regex, r'<strong>\1</strong>', text)

print boldword("www.theshow.com", "the show")
print boldword("my show (video)", "my show (video)")
print boldword("apple ipad", "apple's ipad")
print boldword("stack overflow", "stackoverflow")

выход

>> www.<strong>theshow</strong>.com
>> <strong>my</strong> <strong>show</strong> (<strong>video</strong>)
>> <strong>apple ipad</strong>
>> <strong>stack overflow</strong>
1 голос
/ 20 февраля 2010

В вашем описании мне говорилось, что A) входная переменная неправильно разделена пробелами и B) она не экранирована должным образом.

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

Попробуйте это:

return mark_safe(re.compile((r"\b(%s)\b" % ("|".join(map(re.escape, needle.split(' '))), re.I))).sub(r'<strong>\1</strong>', text))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...