Регулярное выражение Python, поиск префиксов внутри целевой строки - PullRequest
1 голос
/ 15 марта 2012

Мне нужно найти список префиксов слов внутри целевой строки (я хотел бы, чтобы список соответствующих индексов в целевой строке обрабатывался как массив).

  • Я думаю, использование regex должно быть самым чистым способом.
  • Учитывая, что я ищу шаблон "foo", я хотел бы получить в целевой строке такие слова, как "foo", "Foo", "fooing", "Fooing"
  • Учитывая, что я ищу шаблон "foo bar", я хотел бы получить в целевых строковых шаблонах, таких как "foo bar", "Foo bar", "foo Bar", "foo baring" (они все еще все обрабатываются как префиксы, я прав?)

В настоящий момент, после запуска в других сценариях, мой код Python по-прежнему не работает.

  • Я предполагаю, что должен использовать ^ , чтобы соответствовать началу слова в целевой строке (то есть префиксе).
  • Я предполагаю, что мне нужно использовать что-то вроде ^ [fF] , чтобы быть нечувствительным к регистру с первой буквой моего префикса .
  • Я предполагаю, что я должен использовать что-то вроде ". *" , чтобы регулярное выражение могло вести себя как префикс .
  • Я предполагаю, что мне следует использовать \ prefix1 | prefix2 | prefix3 **, чтобы вставить в ** логику ИЛИ много разных префиксов в шаблоне для поиска.

Следующий исходный код не работает, потому что я неправильно устанавливаю txt_pattern.

import re

#              '            '           '            '                     '             '           '
txt_str = "edb foooooo jkds Fooooooo kj fooing jdcnj Fooing ujndn ggng sxk foo baring sh foo Bar djw Foo";
txt_pattern = ''#???

out_obj = re.match(txt_pattern,txt_str)
if out_obj:
   print "match!"
else:
   print "No match!"
  1. Чего мне не хватает?

  2. Как установить txt_pattern?

  3. Можете ли вы предложить мне хороший учебник с минимум рабочих примеров ? На данный момент стандартные учебники с первой страницы поиска Google очень длинные и подробные, и их не так просто понять.

Спасибо!

Ответы [ 5 ]

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

Regex - неправильный подход.Сначала разберите вашу строку в список строк с одним словом на элемент.Затем используйте понимание списка с помощью фильтра.Метод split для строк - это хороший способ получить список слов, тогда вы можете просто сделать [item for item in wordlist if item.startswith("foo")]

Люди целую вечность взламывая неэффективный код, используя замысловатые регулярные выражения, когда все, что им нужно, это несколько строктакие методы, как split, partition, startswith и некоторые выражения или генераторы Python-списков.

Регулярные выражения имеют свое применение, но простой синтаксический анализ строк не является одним из них.

3 голосов
/ 16 марта 2012
>>> s = 'Foooooo jkds Fooooooo kj fooing jdcnj Fooing ujndn ggng sxk foo baring sh foo Bar djw Foo'
>>> regex = '((?i)(foo)(\w+)?)'
>>> compiled = re.compile(regex)
>>> re.findall(compiled, s)
[('Foooooo', 'Foo', 'oooo'), ('Fooooooo', 'Foo', 'ooooo'), ('fooing', 'foo', 'ing'), ('Fooing', 'Foo', 'ing'), ('foo', 'foo', ''), ('foo', 'foo', ''), ('Foo', 'Foo', '')]

(?i) -> без учета регистра
(foo) -> group1 соответствует foo
(\w+) -> group2 соответствует любому другому символу слова

>>> print [i[0] for i in re.findall(compiled, s)]
['Foooooo', 'Fooooooo', 'fooing', 'Fooing', 'foo', 'foo', 'Foo']
3 голосов
/ 15 марта 2012

Я предполагаю, что мне нужно использовать ^, чтобы соответствовать началу слова в целевой строке (то есть префиксе).

Нет, ^ - это привязка, которая соответствует только началу строки. Вместо этого вы можете использовать \b, что означает границу слова (но не забывайте избегать обратной косой черты внутри строкового литерала или использовать необработанный строковый литерал).

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

1 голос
/ 15 марта 2012

Попробуйте использовать этот инструмент для проверки некоторых вещей: http://www.pythonregex.com/

Используйте эту ссылку: docs.python.org/howto/regex.html

0 голосов
/ 15 марта 2012

Я бы использовал что-то вроде этого для вашего регулярного выражения:

\b(?:([Ff]oo [Bb]ar)|([Ff]oo))\w*

Внутри группы без захвата вы должны отделить каждый префикс |, я также поместил каждый префикс внутри его собственного захватаgroup, чтобы вы могли сказать, какому префиксу соответствует данная строка, например:

for match in re.finditer(r'\b(?:([Ff]oo [Bb]ar)|([Ff]oo))\w*', txt_str):
    n = 1
    while not match.group(n):
        n += 1
    print "Prefix %d matched '%s'" % (n, match.group(0))

Вывод:

Prefix 2 matched 'foooooo'
Prefix 2 matched 'Fooooooo'
Prefix 2 matched 'fooing'
Prefix 2 matched 'Fooing'
Prefix 1 matched 'foo baring'
Prefix 1 matched 'foo Bar'
Prefix 2 matched 'Foo'

Убедитесь, что сначала вы ставите более длинные префиксы, если ставите *Префикс 1011 * перед префиксом foo bar соответствует 'foo' в 'foo bar'.

...