2017-02-08 2 views
1

Я пытаюсь разобрать многострочный текст с помощью библиотеки python. Я играл с ним некоторое время и не могу понять, как эффективно работать с новыми символами. Ниже приведен пример. Следующее поведение имеет смысл. Я видел this comment от Erik Rose в скудных вопросах, но я не мог понять, как его реализовать без ошибок. Спасибо за любые советы здесь ...Анализ многострочного текста с использованием библиотеки Parsimonious Python

singleline_text = '''\ 
FIRST something cool''' 

multiline_text = '''\ 
FIRST something very 
     cool 
SECOND more awesomeness   
''' 

grammar = Grammar(
    """ 
    bin   = ORDER spaces description 
    ORDER   = 'FIRST'/'SECOND' 
    spaces  = ~'\s*' 
    description = ~'[A-z0-9 ]*' 
    """) 

работает нормально для вывода одной строки, print(grammar.parse(singleline_text)) дает:

<Node called "bin" matching "FIRST something cool"> 
    <Node called "ORDER" matching "FIRST"> 
     <Node matching "FIRST"> 
    <RegexNode called "spaces" matching " "> 
    <RegexNode called "description" matching "something cool"> 

Но многострочный создает проблемы, и я не смог решить на основе приведенной выше ссылке, print(grammar.parse(multiline_text)) дает:

--------------------------------------------------------------------------- 
IncompleteParseError      Traceback (most recent call last) 
<ipython-input-123-c346891dc883> in <module>() 
----> 1 print(grammar.parse(multiline_text)) 

/Users/me/anaconda3/lib/python3.6/site-packages/parsimonious/grammar.py in parse(self, text, pos) 
    121   """ 
    122   self._check_default_rule() 
--> 123   return self.default_rule.parse(text, pos=pos) 
    124 
    125  def match(self, text, pos=0): 

/Users/me/anaconda3/lib/python3.6/site-packages/parsimonious/expressions.py in parse(self, text, pos) 
    110   node = self.match(text, pos=pos) 
    111   if node.end < len(text): 
--> 112    raise IncompleteParseError(text, node.end, self) 
    113   return node 
    114 

IncompleteParseError: Rule 'bin' matched in its entirety, but it didn't consume all the text. The non-matching portion of the text begins with ' 
     cool 
SECOND' (line 1, column 23). 

Вот одна вещь, которую я попробовал, что не получилось:

grammar2 = Grammar(
    """ 
    bin   = ORDER spaces description newline 
    ORDER   = 'FIRST'/'SECOND' 
    spaces  = ~'\s*' 
    description = ~'[A-z0-9 \n]*' 
    newline  = ~r'#[^\r\n]*' 
    """) 

print(grammar2.parse(multiline_text)) 

(усеченный от трассировки стека 211 строки):

ERROR:root:An unexpected error occurred while tokenizing input 
The following traceback may be corrupted or invalid 
The error message is: ('EOF in multi-line string', (1, 4)) 

--------------------------------------------------------------------------- 
SyntaxError        Traceback (most recent call last) 

... 


VisitationError: SyntaxError: EOL while scanning string literal (<unknown>, line 1) 

Parse tree: 
<Node called "spaceless_literal" matching "'[A-z0-9 
]*'"> <-- *** We were here. *** 
    <RegexNode matching "'[A-z0-9 
    ]*'"> 

ответ

1

Похоже, что вам нужно повторить бен элемент в вашей грамматике:

grammar = Grammar(
    r""" 
    one   = bin + 
    bin   = ORDER spaces description newline 
    ORDER   = 'FIRST'/'SECOND' 
    newline  = ~"\n*" 
    spaces  = ~"\s*" 
    description = ~"[A-z0-9 ]*"i 
    """) 

с этим вы можете разобрать вещи например:

multiline_text = '''\ 
FIRST something very cool 
SECOND more awesomeness  
SECOND even better 
''' 
+0

Это хорошо работает, чтобы разобраться с одной записью на каждой строке ... Спасибо. Я пытаюсь использовать ваши советы для решения проблемы с упаковкой, где описание может охватывать несколько строк. – Mark