Разбор параметров из строки с помощью регулярного выражения с группами в Python - PullRequest
1 голос
/ 10 июля 2019

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

Пример:

some text [more text :Parameter1] more text [more (:Parameter2)]

Моя цель - получить два матча следующим образом:

Полное совпадение: [текст: Parameter1]

Группа 1:: Параметр1

Полное совпадение: [more (: Parameter2)]

Группа 1:: Параметр2

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

r"\\[.*?([:\$].*?)]" 

и в этих случаях я получаю:

Полное соответствие: [текст: Parameter2]

Группа 1:: Параметр2)

Обратите внимание, что group1 идет с последней круглой скобкой.

Я не мог найти способ удалить его. Цени любую помощь.

тесты regex101

Спасибо.

Ответы [ 5 ]

1 голос
/ 10 июля 2019

Если вы хотите, чтобы параметр находился между открывающей и соответствующей закрывающей скобкой, вы можете использовать отрицательные классы символов [^][()$:] для соответствия любому символу, который не входит в класс символов.

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

\[[^][()$:]*(?:\(([:$][^][()$:]+)\)|([:$][^][()$:]+))\]

О шаблоне

  • \[ Соответствие [
  • [^][()$:]* Соответствие 0+ раз любому символу, который не входит в класс символов
  • (?: Группа без захвата
    • \( Совпадение (
    • ( Группа захвата 1
      • [:$][^][()$:]+ Совпадение $ или :, затем сопоставление 1+ символов, не принадлежащих к классу персонажей
    • ) Закрыть группу 1
    • \) Совпадение )
    • | Или
    • ( Группа захвата 2
      • [:$][^][()$:]+ Совпадение $ или :, затем сопоставление 1+ символов, не принадлежащих к классу персонажей
    • ) Закрыть группу 2
  • ) Закрыть группу без захвата
  • \] Совпадение ]

Regex demo

1 голос
/ 10 июля 2019

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

(\[[^:]+([:$][^])]+)[])]+)

Это будет быстрее, чем использование ленивых квантификаторов.

Детали регулярного выражения:

  • \[ совпадений [
  • [^:]+ соответствует 1 или более раз любым символам, кроме :
  • ([:$][^])]+) вторая группа:
    • [:$] соответствует либо :, либо $
    • [^])]+ соответствует 1 или более раз любым символам, кроме ] или )
  • [])]+ соответствует ] и / или ) хотя бы один раз

Демо

import re
s = 'some text [more text :Parameter1] more text [more (:Parameter2)]'

print(re.findall(r'(\[[^:]+([:$][^])]+)[])]+)', s)

Output:
[('[more text :Parameter1]', ':Parameter1'), '[more text (:Parameter2)]', ':Parameter2')]
1 голос
/ 10 июля 2019

С расширенным регулярным выражением:

import re

s = 'some text [more text :Parameter1] more text [more (:Parameter2)]'
res = re.findall(r'(\[[^\[\]:$]+\(?([:$][^:$)]+)\)?\])', s)
print(res)

Вывод (в формате (<full_match>, <group_1>)):

[('[more text :Parameter1]', ':Parameter1'), ('[more (:Parameter2)]', ':Parameter2')]
0 голосов
/ 10 июля 2019

Я бы предложил простое выражение,

(\[[^(:]+([^]]+)\])

, а затем написание сценария остальной части проблемы, чтобы избежать осмотров.


Тест

import re

regex = r"(\[[^(:]+([^]]+)\])"

test_str = "some text [more text :Parameter1] more text [more (:Parameter2)]"

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

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

0 голосов
/ 10 июля 2019

Это регулярное выражение делает то, что вы хотите:

\[.*?([:\$].*?)\)?]

Выход:

[more text :Parameter1]
:Parameter1
[more (:Parameter2)]
:Parameter2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...