Извлечение ВСЕХ совпадений регулярного выражения в Python - PullRequest
1 голос
/ 28 октября 2009

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

r'\A(("[\w\s]+"|\w+)\s+)*\Z'

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

r'("[\w\s]+"|\w+)'

часть. Так, например

>>> parse('foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']

Есть ли хороший способ сделать это с помощью Python Re?

Многие вещи не совсем работают. Например

>>> re.match(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
'"bob"'

возвращает только последний из найденных совпадений. С другой стороны

>>> re.findall(r'("[\w\s]+"|\w+)', 'foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']

но он также принимает некорректные выражения, такие как

>>> re.findall(r'("[\w\s]+"|\w+)', 'foo "bar b-&&az" "bob" ')
['foo', 'bar', 'b', 'az', '" "', 'bob']

Так есть ли способ использовать исходное регулярное выражение и получить все элементы, которые соответствуют группе 2? Что-то вроде

>>> re.match_multigroup(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
['foo', '"bar baz"', '"bob"']
>>> re.match_multigroup(r'("[\w\s]+"|\w+)', 'foo "bar b-&&az" "bob" ')
None

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

>>> re.match_multigroup(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
['foo', 'bar baz', 'bob']

потому что тогда я не знаю, цитировался Боб или нет.

Ответы [ 3 ]

2 голосов
/ 28 октября 2009

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

>>> s = 'foo "bar baz" "bob" '
>>> for i in csv.reader([s], delimiter=' '):
    print(i)


['foo', 'bar baz', 'bob', '']
1 голос
/ 30 октября 2009

Хорошо, я решил сделать это в два этапа.

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

def parse(expr):
    if re.match(r'\A(("[\w\s]+"|\w+)\s+)*\Z', expr):
        return re.findall(r'("[\w\s]+"|\w+)', expr)

Итак:

>>> parse('foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']
>>> parse('foo "bar b-&&az" "bob" ')
>>> parse('foo "bar" ')
['foo', '"bar"']
>>> parse('"foo" bar ')
['"foo"', 'bar']
>>> parse('foo"bar baz" "bob" ')
>>> parse('&&')

Я почти на 90% уверен, что этот метод работает надлежащим образом для всех строк, но мне все равно было бы интересно, если бы у кого-то было более общее решение, мне это кажется своего рода глупым.

Спасибо SilentGhost и Алану Муру за помощь. Раньше я не знал о взглядах на Python CSV или Regex, мне было бы полезно узнать о них.

1 голос
/ 28 октября 2009

Вот решение, которое разбивает любой пробел, который не находится внутри пары кавычек:

re.split('\s+(?=[^"]*(?:"[^"]*"[^"]*)*$)', target)

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

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