Разделение строк в Python

У меня есть такая строка:

это [тест в скобки] "тест с цитатами"

Я пытаюсь написать что-то на Python, чтобы разделить его на пробелы, игнорируя пробелы в квадратных скобках и кавычках. Результат, который я ищу:

["это", "есть", "проверка скобок" и "проверка кавычек"]

Скобки гнездятся? Могут ли в кавычках быть не совпадающие скобки? А как насчет несоответствующих кавычек или скобок? Каков правильный результат для следующего: [[вложенные скобки] тест] "бюстгальтер [в кавычках" "ket] в кавычках" [цитата "в скобках]"]

Jouni K. Seppänen 24.10.2008 21:38
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
7
1
5 074
6

Ответы 6

Вот упрощенное решение, которое работает с вашим тестовым вводом:

import re
re.findall('\[[^\]]*\]|\"[^\"]*\"|\S+',s)

Это вернет любой код, который соответствует либо

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

Это работает с вашим примером, но может не работать для многих реальных строк, с которыми вы можете столкнуться. Например, вы не сказали, чего ожидаете от несбалансированных скобок или кавычек, или как вы хотите, чтобы работали одинарные кавычки или escape-символы. Однако для простых случаев описанного выше может быть достаточно.

Это оставляет кавычки и квадратные скобки. Это не совсем то, о чем просили.

Sanjaya R 29.10.2008 21:46

Вот упрощенный синтаксический анализатор (протестированный на вашем примере ввода), который вводит шаблон проектирования State.

В реальном мире вы, вероятно, захотите создать настоящий парсер, используя что-то вроде PLY.

class SimpleParser(object):

    def __init__(self):
        self.mode = None
        self.result = None

    def parse(self, text):
        self.initial_mode()
        self.result = []
        for word in text.split(' '):
            self.mode.handle_word(word)
        return self.result

    def initial_mode(self):
        self.mode = InitialMode(self)

    def bracket_mode(self):
        self.mode = BracketMode(self)

    def quote_mode(self):
        self.mode = QuoteMode(self)


class InitialMode(object):

    def __init__(self, parser):
        self.parser = parser

    def handle_word(self, word):
        if word.startswith('['):
            self.parser.bracket_mode()
            self.parser.mode.handle_word(word[1:])
        elif word.startswith('"'):
            self.parser.quote_mode()
            self.parser.mode.handle_word(word[1:])
        else:
            self.parser.result.append(word)


class BlockMode(object):

    end_marker = None

    def __init__(self, parser):
        self.parser = parser
        self.result = []

    def handle_word(self, word):
        if word.endswith(self.end_marker):
            self.result.append(word[:-1])
            self.parser.result.append(' '.join(self.result))
            self.parser.initial_mode()
        else:
            self.result.append(word)

class BracketMode(BlockMode):
    end_marker = ']'

class QuoteMode(BlockMode):
    end_marker = '"'

Работает только для котировок.

rrr = []
qqq = s.split('\"')
[ rrr.extend( qqq[x].split(), [ qqq[x] ] )[ x%2]) for x in range( len( qqq ) )]
print rrr

Вот более процедурный подход:

#!/usr/bin/env python

a = 'this is [bracket test] "and quotes test "'

words = a.split()
wordlist = []

while True:
    try:
        word = words.pop(0)
    except IndexError:
        break
    if word[0] in '"[':
        buildlist = [word[1:]]
        while True:
            try:
                word = words.pop(0)
            except IndexError:
                break
            if word[-1] in '"]':
                buildlist.append(word[:-1])
                break
            buildlist.append(word)
        wordlist.append(' '.join(buildlist))
    else:
        wordlist.append(word)

print wordlist

Чтобы заполнить пост Брайана и точно сопоставить ответ:

>>> import re
>>> txt = 'this is [bracket test] "and quotes test "'
>>> [x[1:-1] if x[0] in '["' else x for x in re.findall('\[[^\]]*\]|\"[^\"]*\"|\S+', txt)]
['this', 'is', 'bracket test', 'and quotes test ']

Не поймите неправильно весь используемый синтаксис: это не несколько статусов в одной строке, а один функциональный статус (более устойчивый к ошибкам).

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

Результат этого можно найти здесь; обратите внимание, что это может быть излишним, и это предоставит вам что-то, что позволит вам анализировать операторы как с скобками, так и с круглыми скобками, одинарными и двойными кавычками, как вам нужно. Например, вы можете разобрать что-то вроде этого (пример, написанный на Common Lisp):

(defun hello_world (&optional (text "Hello, World!"))
    (format t text))

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

Идея в основном заключается в настраиваемой реализации конечного автомата, который поэтапно строит абстрактное синтаксическое дерево. Я рекомендую вам посмотреть исходный код (см. Ссылку выше), чтобы понять, как это сделать. Он поддерживает регулярные выражения, но попробуйте написать систему, используя RE, а затем попытайтесь расширить ее (или даже понять) позже.

Другие вопросы по теме