Получить все возможные совпадения для регулярных выражений (в python)?

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

Строка, которую я пытаюсь разобрать:

foo-foobar-foobaz 

Я использую регулярное выражение:

 (.*)-(.*) >>> s = "foo-foobar-foobaz" >>> matches = re.finditer(r'(.*)-(.*)', s) >>> [match.group(1) for match in matches] ['foo-foobar'] 

Я хочу матч (foo и foobar-foobaz), но, похоже, он только получает (foo-foobar и foobaz).

  • Python / YACC: разрешение конфликта сдвига / сокращения
  • Правильный способ обработки нескольких форм на одной странице в Django
  • В чем разница между идиомами для подачи изображения Matplotlib с помощью Flask?
  • uWSGI, ImportError: Нет модуля с именем site на Ubuntu
  • Как читать файл макета v7.3 через h5py?
  • urllib2 / запросы и относительный путь HTTP
  • Получить 'unc' путь в OSX установленной долей
  • Как вычисляется значение R2 в Scikit?
  • 3 Solutions collect form web for “Получить все возможные совпадения для регулярных выражений (в python)?”

    Нет проблем:

     >>> regex = "([^-]*-)(?=([^-]*))" >>> for result in re.finditer(regex, "foo-foobar-foobaz"): >>> print("".join(result.groups())) foo-foobar foobar-foobaz 

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

    Я также использовал [^-]* вместо .* Потому что точка также соответствует разделителю, которого вы, вероятно, не хотите.

    Это не то, что двигатели регулярных выражений имеют тенденцию делать. Я не знаю, может ли Python. Perl может использовать следующее:

     local our @matches; "foo-foobar-foobaz" =~ / ^(.*)-(.*)\z (?{ push @matches, [ $1, $2 ] }) (*FAIL) /xs; 

    Эта конкретная проблема, вероятно, может быть решена с использованием механизма регулярных выражений на многих языках, используя следующую технику:

     my @matches; while ("foo-foobar-foobaz" =~ /(?=-(.*)\z)/gsp) { push @matches, [ ${^PREMATCH}, $1 ]; } 

    ( ${^PREMATCH} относится к тому, что встречается там, где соответствует регулярное выражение, а $1 относится к тому, что соответствует первому () .)

    Но вы можете легко решить эту конкретную проблему за пределами механизма регулярных выражений:

     my @parts = split(/-/, "foo-foobar-foobaz"); my @matches; for (1..$#parts) { push @matches, [ join('-', @parts[0..$_-1]), join('-', @parts[$_..$#parts]), ]; } 

    Извините за использование синтаксиса Perl, но должен быть в состоянии получить эту идею. Переводы на Python приветствуются.

    Если вы хотите обнаружить совпадающие совпадения, вам придется реализовать его самостоятельно – по существу, для строки foo

    1. Найти первое совпадение, начинающееся с индекса строки i
    2. Запустите функцию сопоставления снова против foo[i+1:]
    3. Повторите шаги 1 и 2 в инкрементно короткой оставшейся части строки.

    Это становится сложнее, если вы используете группы захвата произвольной длины (например, (.*) ), Потому что вы, вероятно, не хотите, чтобы как foo-foobar и oo-foobar качестве совпадений, поэтому вам нужно будет сделать дополнительный анализ для перемещения i даже дальше, чем только один матч; вам нужно будет переместить его на всю длину значения первой захваченной группы, плюс одну.

    Python - лучший язык программирования в мире.