Seite 1 von 1

regex text extrahieren

Verfasst: Donnerstag 10. Februar 2022, 21:32
von Fire Spike
Hallo Leute.
Ich versuche aktuell aus einem String einen Wert zu extrahieren.

Zum Beispiel brauche ich von dem

Code: Alles auswählen

Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_exe_path )
nur das:

Code: Alles auswählen

Error, icon path %r does not exist.
Das funktioniert auch super mit dem folgendem Ausdruck

Code: Alles auswählen

(_logger|general)(.+\s?\")(.+)(\".*\))
Es kann jetzt aber auch vorkommen, dass ein solcher String kommt:

Code: Alles auswählen

Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""" )
Versucht habe ich es mit

Code: Alles auswählen

(_logger|general)(.+\s?\"+)(.+)(\"+.*\))
Es funktioniert aber nicht und ich weiss nicht warum.
Leider ist es zusätzlich noch so dass viele von solchen Teilen zusammengehängt sind, mit zufälligem Zeug noch dazwischen.
Wie ich dort die Werte herausholen kann habe ich auch nicht herausgefunden.
Könnt ihr mir helfen?

Re: regex text extrahieren

Verfasst: Donnerstag 10. Februar 2022, 22:17
von Sirius3
Da es sich offentsichtlich um Python-Code handelt, ist es keine gute Idee, da mit regulären Ausdrücken drauf loszugehen. Dafür gibt es das ast-Modul.

Re: regex text extrahieren

Verfasst: Sonntag 13. Februar 2022, 17:49
von LukeNukem
Fire Spike hat geschrieben: Donnerstag 10. Februar 2022, 21:32 Könnt ihr mir helfen?
Neben dem Tipp mit dem Python-Builtin-Modul "ast" gibt es auch einige sehr leistungsfähige Parsergeneratoren für Python, ich persönlich mag Lark [1]. Damit kann man neben Deinem Python-Code auch andere Quelltexte und -Formate sehr flexibel und schnell parsen, ein Beispiel für Deine Anforderung sähe dann etwa so aus:

Code: Alles auswählen

#!/usr/bin/env python
from time import perf_counter

from lark import Lark, Tree, Token, UnexpectedEOF

GRAMMAR = '''
line: module "(" formatstring parameters* ")"
module: MODULE_TERM
MODULE_TERM: /[A-Za-z._]+/
formatstring: FORMATSTRING_TERM
FORMATSTRING_TERM: STRING | LONG_STRING | ESCAPED_STRING
parameters: "%" parameterlist 
parameterlist: parameter | "(" parameter ")" | "(" parameter ("," parameter)* ")"
parameter: /[A-Za-z._]+/
string: STRING | LONG_STRING | ESCAPED_STRING
%import python.STRING
%import python.LONG_STRING
%import common.ESCAPED_STRING
%import common.WS
%ignore WS
'''

LINES = '''
Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""" )
Hans.Wurst.dings("blabla")
Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_exe_path )
Klausdieter("juhuuu")
Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""" )
Hans.Wurst.dings("blabla")
Blabla
Hans.Wurst.dings("blabla")
'''

class ScanTree(Tree):
    def get_value(self, name):
        return next(self.scan_values(lambda x: isinstance(x, Token) and x.type == name)).value
    

if __name__ == '__main__':

    # create parser
    s0 = perf_counter()
    parser = Lark(GRAMMAR, start='line', tree_class=ScanTree)
    s1 = perf_counter()

    # read line-by-line
    count = 0
    for line in LINES.split('\n'):
        if line.strip():
            count += 1
            print('line -> ', line.strip(), ' ')
            try:
                # parse each line
                tree = parser.parse(line)
                print('  %s -> %s'%(tree.get_value('MODULE_TERM'), tree.get_value('FORMATSTRING_TERM')))
            except UnexpectedEOF as e: # if we can't parse the line
                print('  Sorry, cannot parse line "%s"'%(line))
            print()
            
    s2 = perf_counter()
    print('build parser: %8.4f ms'%((s1 - s0)*1000))
    print('run   parser: %8.4f ms for %d lines'%((s2 - s1)*1000, count))
    print('line  parser: %8.4f ms'%(((s2 - s1)*1000) / count))
[1] https://lark-parser.readthedocs.io/en/latest/