





Вот упрощенное решение, которое работает с вашим тестовым вводом:
import re
re.findall('\[[^\]]*\]|\"[^\"]*\"|\S+',s)
Это вернет любой код, который соответствует либо
Это работает с вашим примером, но может не работать для многих реальных строк, с которыми вы можете столкнуться. Например, вы не сказали, чего ожидаете от несбалансированных скобок или кавычек, или как вы хотите, чтобы работали одинарные кавычки или escape-символы. Однако для простых случаев описанного выше может быть достаточно.
Это оставляет кавычки и квадратные скобки. Это не совсем то, о чем просили.
Вот упрощенный синтаксический анализатор (протестированный на вашем примере ввода), который вводит шаблон проектирования 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, а затем попытайтесь расширить ее (или даже понять) позже.
Скобки гнездятся? Могут ли в кавычках быть не совпадающие скобки? А как насчет несоответствующих кавычек или скобок? Каков правильный результат для следующего: [[вложенные скобки] тест] "бюстгальтер [в кавычках" "ket] в кавычках" [цитата "в скобках]"]