2017-04-06 17 views
0

ich auf einem Python-Parser an Arbeitslage mit und ich habe Eingang in Form zu analysieren:PLY: unzulässiges Zeichen ‚+‘

VAR VAR1 001 
+000 000 000 000 

Wo der Code eine Variable VAR genannt schaffen würde 1 weisen Sie dann die Wert 0 bis es

die Regex ich für die Instanciation geschrieben hat, ist:

t_INST = r'[\+|-]0[ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9]' 

jedoch, wenn mein Programm ausgeführt wird, PLY druckt die folgenden:

Illegal character '+' 

A reproducer folgt:

import ply.lex as lex 

tokens = ['INST'] 
t_INST = r'[+-]0[ ](\d{3}[ ]){3}\d{3}'; 
t_ignore = ' \t' 
def t_error(t): 
    print("Illegal character '%s'" % t.value[0]) 
    t.lexer.skip(1) 

lexer = lex.lex() 

def parse(input_string): 
    ret = [] 
    lexer.input (input_string) 
    while True: 
     tok = lexer.token() 
     if not tok: 
      break  # No more input 
     ret.append((tok.type, tok.value)) 
    return ret 

print parse("+0 000 000 000") 
+0

Sie sollten \ d verwenden Zeichen zu bezeichnen und nutzen auch {} bezeichnen Sequenzen wiederholen: [\ + -] (\ d {3} \ s?) {4} – Neil

+0

Warum der Backslash? Sie möchten das in einem normalen Kontext, aber es macht keinen Sinn in einer Zeichenklasse.Wenn "|" kein gültiges erstes Zeichen ist, wollen Sie wahrscheinlich auch '[+ -]', nicht '[+ | -]'. –

+0

Übrigens wäre es hilfreich, wenn Ihr Reproduzierer - solange er wie * minimal * bleibt - bis zu dem Punkt erweitert wird, an dem er * vollständig * und * überprüfbar * ist, wie in http://stackoverflow.com/ angegeben. Hilfe/mcve. Gerade jetzt muss jemand ziemlich viel Arbeit machen, um den Fehler zu reproduzieren. –

Antwort

0

Die Linie:

print parse("+0 000 000 000") 

nicht Ihr angegebenes Eingabeformat von

VAR VAR1 001 
+000 000 000 000 

Wenn die tatsächlichen Daten übereinstimmen ist in der gleichen Form wie +0 000 000 000, dann möchten Sie eigentlich:

t_INST = r'[+-]0\s(?:\d{3}\s){2}\d{3}' 

... mit dem Ausgang: [('INST', '+0 000 000 000')]

+0

Diese Art der Regex gab ich in meiner Antwort mit dem '\ s' für Verknüpfung und nicht einfangende Gruppe. Das klingt eher nach einem Kommentar für meine Frage. Außerdem haben Sie '{2}' verwendet und sollten '{3}' –

+0

sein. Für die Testdaten des OPs, nein, sollte es ** wirklich ** '{2}' sein. Ihre Kommentare sind irreführend bezüglich des tatsächlich verwendeten Datenformats. (Deshalb habe ich die Zeit damit verbracht, sie dazu zu bringen, einen echten Reproduzierer zur Verfügung zu stellen, anstatt eine Antwort direkt zu schreiben). –

1

Sie müssen + innerhalb Charakterklassen nicht entkommen. Sie verwenden können:

t_INST = r'[+|-]0[ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9]' 
    this-----^ 

Wie auch immer, können Sie Ihre Regex wie folgt verkürzen:

t_INST = r'[+|-]0[ ][0-9]{3}[ ][0-9]{3}[ ][0-9]{3}[ ][0-9]{3}' 

Oder auch:

t_INST = r'[+|-]0[ ]([0-9]{3}[ ]){3}[0-9]{3}' 

auch bemerkt, dass Sie [+|-] verwendet, ist dies eine Zeichenklasse und funktioniert nicht mit Änderungen, also müssen Sie es in [+-] ändern.

Also, eine endgültige regex (\d als Abkürzung für [0-9] verwenden) wäre:

t_INST = r'[+-]0[ ](\d{3}[ ]){3}\d{3}' 

Btw, Sie Beispieltext sagt:

+000 000 000 000 

Aber die regex Sie Streichhölzer verwenden diese:

Also, wenn Sie die Daten, die Sie übereinstimmen möchten, ist +000 000 000 000, dann müssen Sie die Regex ändern:

t_INST = r'[+-](\d{3}[ ]){3}\d{3}' 
+0

... das Problem hier (dh das schlechte Verhalten, aufgrund dessen ich mich entschieden habe, eine konkurrierende Antwort zu schreiben, anstatt mich dazu zu äußern), ist, dass Sie eine Antwort geschrieben haben, ohne tatsächlich einen echten Reproduzenten zu haben, der ihr Problem verursachen könnte, und also ohne Gewissheit, dass Sie * wirklich * gewusst haben, was das OP-Problem tatsächlich war. Selbst wenn 're.compile (r '[\ + | -]') .match ('+')' nicht funktionieren würde, würde ich zustimmen, dass es starke Gründe für Spekulationen geben würde, aber das ist hier nicht der Fall: Der ursprüngliche Code war * schlecht *, aber (testbar!) Nicht gebrochen auf irgendeinem der ursprünglich angegebenen Gründe. –

+0

... tatsächlich, re.compile (r '[\ + | -] 0 [] [0-9] [0-9] [0-9] [] [0-9] [0-9] [ 0-9] [] [0-9] [0-9] [0-9] [] [0-9] [0-9] [0-9] '). Match (' + 0 000 000 000 000 ') 'gibt eine Übereinstimmung zurück. –

Verwandte Themen