извлечь части строки в Python

1

Мне нужно разобрать входную строку в python и извлечь из нее определенные части.

формат строки

(xx,yyy,(aa,bb,...)) // Inner parenthesis can hold one or more characters in it

Я хочу, чтобы функция возвращала xx, yyyy и список, содержащий aa, bb... etc

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

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

def processInput(inputStr):
    value = inputStr.strip()[1:-1]
    parts = value.split(',', 2)
    return parts[0], parts[1], (parts[2].strip()[1:-1]).split(',')
  • 1
    Если бы внутренние значения были заключены в кавычки, вы могли бы просто eval() , хотя я, конечно, не рекомендовал бы это :)
  • 0
    gskinner.com/RegExr
Теги:

6 ответов

3
Лучший ответ

Если у вас аллергия на RE, вы можете использовать pyparsing:

>>> import pyparsing as p
>>> ope, clo, com = map(p.Suppress, '(),')
>>> w = p.Word(p.alphas)
>>> s = ope + w + com + w + com + ope + p.delimitedList(w) + clo + clo
>>> x = '(xx,yyy,(aa,bb,cc))'
>>> list(s.parseString(x))
['xx', 'yyy', 'aa', 'bb', 'cc']

pyparsing также позволяет легко контролировать точную форму результатов (например, группируя последние 3 элемента в свой собственный подсписок), если хотите. Но я думаю, что самый приятный аспект - как естественный (в зависимости от того, сколько места вы хотите посвятить ему), вы можете сделать "грамматическую спецификацию" прочитанной: открытый парен, слово, запятую, слово, запятую, открытую paren, разделительный список слов, две закрытые круглые скобки (если вы считаете, что присвоение s выше не так просто читать, я полагаю, что это моя ошибка за то, что вы не выбрали более длинные идентификаторы; -).

  • 0
    Алекс, ты дурак с серебряным языком! Я думаю, что мы, вероятно, отправили в течение минуты друг от друга!
  • 0
    @ Пол, да - твоего поста не было, так как я начал писать свой, и я уверен, что обратное тоже верно, поэтому мы, должно быть, писали их почти одновременно!
3

Если вложенность ваших скобок может быть сколь угодно глубокой, то regexen не будет работать, вам понадобится конечный автомат или синтаксический анализатор. Pyparsing поддерживает рекурсивные грамматики с использованием класса forward-declaration Forward:

from pyparsing import *

LPAR,RPAR,COMMA = map(Suppress,"(),")
nestedParens = Forward()
listword = Word(alphas) | '...'
nestedParens << Group(LPAR + delimitedList(listword | nestedParens) + RPAR)

text = "(xx,yyy,(aa,bb,...))"
results = nestedParens.parseString(text).asList()
print results

text = "(xx,yyy,(aa,bb,(dd,ee),ff,...))"
results = nestedParens.parseString(text).asList()
print results

Печать

[['xx', 'yyy', ['aa', 'bb', '...']]]
[['xx', 'yyy', ['aa', 'bb', ['dd', 'ee'], 'ff', '...']]]
  • 0
    +1, потому что он демонстрирует несколько более продвинутых функций pyparsing то время как я придерживался самых основ ;-)
2

Как насчет этого?

>>> import ast
>>> import re
>>>
>>> s="(xx,yyy,(aa,bb,ccc))"
>>> x=re.sub("(\w+)",'"\\1"',s)
# '("xx","yyy",("aa","bb","ccc"))'
>>> ast.literal_eval(x)
('xx', 'yyy', ('aa', 'bb', 'ccc'))
>>>
2

Пусть используются регулярные выражения!

/\(([^,]+),([^,]+),\(([^)]+)\)\)/

Соответствует этому, первая группа захвата содержит xx, вторая содержит yyy, разделяет третью на ,, и у вас есть свой список.

  • 0
    Абсолютно не связанный в стороне .. это напоминает мне об этом XKCD: xkcd.com/208
  • 0
    Использование регулярных выражений, безусловно, является одним из хороших способов, есть ли способ создать выражение вроде sortof reverse printf и использовать его для извлечения необходимых частей?
Показать ещё 1 комментарий
1

Я не знаю, что это лучше, но это другой способ сделать это. Использование ранее предложенного регулярного выражения

 def processInput(inputStr):
        value = [re.sub('\(*\)*','',i) for i in inputStr.split(',')]
        return value[0], value[1], value[2:]

Кроме того, вместо регулярного выражения вы можете использовать две связанные функции замены.

0

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

import re
parser_re = re.compile(r'\(([^,)]+),([^,)]+),\(([^)]+)\)')
def parse(input):
    m = parser_re.match(input)
    if m:
        first = m.group(1)
        second = m.group(2)
        rest = m.group(3).split(",")
        return (first, second, rest)
    else:
        return None

print parse( '(xx,yy,(aa,bb,cc,dd))' )
print parse( 'xx,yy,(aa,bb,cc,dd)' ) # doesn't parse, returns None

# can use this to unpack the various parts.
# first,second,rest = parse(...)

Печать

('xx', 'yy', ['aa', 'bb', 'cc', 'dd'])
None

Ещё вопросы

Сообщество Overcoder
Наверх
Меню