Hilfe bei regular expression

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mati
User
Beiträge: 68
Registriert: Dienstag 6. Juni 2006, 16:54

Hallo,
ich habe Probleme eine regex zu basteln:

folgender string:
st = "...TEXXXXT\n 2.0 4.5 0.1 8.9\n CONSTANT 111 222 333 \nENDE\nWeiterer Text...."

dieses bruchstück taucht sehr oft vor in einem gewaltigen string. Oben ist nur ein Ausschnitt gezeigt wobei aber die wichtige stelle herausgeschrieben ist.
Schlüsselwort ist CONSTANT. Die Zahlen die vor CONSTANT kommen und die Zahlen danach möchte ich herauspfrimeln und in genau ein Multitupel fassen
-> (2.0, 4.5, 0.1, 8.9, 111, 222, 333)

das ergebnis wären also viele Multitupel die immer Zahlen beinhalten die sich "um das wort CONSTANT befinden"

Bisheriger Ansatz:

Code: Alles auswählen

rgx = re.compile(r'[0-9]+.[0-9]*(\s*)]*CONSTANT(.*?)(?=ENDE)' , re.DOTALL | re.IGNORECASE)
wäre nett wenn mir jemand helfen könnte wie ich auf effizienteste weise einfach diese zusammengehörigen werte bekommen könnte DANKE
BlackJack

Mati hat geschrieben:wäre nett wenn mir jemand helfen könnte wie ich auf effizienteste weise einfach diese zusammengehörigen werte bekommen könnte DANKE
Also ich finde PyParsing oft einfacher als reguläre Ausdrücke. Sowohl beim Schreiben als auch beim Verstehen, falls man sich den Quelltext in einem Jahr nochmal anschaut.

Code: Alles auswählen

from pyparsing import CaselessKeyword, OneOrMore, Regex, Suppress

source = """\
...TEXXXXT
         2.0   4.5         0.1  8.9
          CONSTANT 111   222   333
ENDE
Weiterer Text....
 5 6 7
CoNsTaNt 42
4711 23
BlaH
"""

number = Regex(r'[0-9]+(\.[0-9]+)?')
constant = Suppress(CaselessKeyword('CONSTANT'))
grammar = OneOrMore(number) + constant + OneOrMore(number)
print [tuple(map(float, match[0])) for match in grammar.scanString(source)]
Das Ergebnis ist:

Code: Alles auswählen

[(2.0, 4.5, 0.10000000000000001, 8.9000000000000004, 111.0, 222.0, 333.0),
 (5.0, 6.0, 7.0, 42.0, 4711.0, 23.0)]
Falls ``ENDE`` wirklich als Schlüsselwort an der entsprechenden Stelle vorkommen muss, dann lässt sich das sehr einfach hinzufügen.

Ansonsten kann man natürlich auch einen kleinen Parser von Hand schreiben:

Code: Alles auswählen

def iter_words(lines):
    for line in lines:
        for word in iter(line.split()):
            yield word

def parse(words):
    seen_constant = False
    result = list()
    for word in words:
        try:
            result.append(float(word))
        except ValueError:
            if seen_constant:
                yield tuple(result)
                seen_constant = False
                result = list()
            elif word.upper() == 'CONSTANT':
                seen_constant = True
    if seen_constant:
        yield tuple(result)

print list(parse(iter_words(source.split('\n'))))
Mati
User
Beiträge: 68
Registriert: Dienstag 6. Juni 2006, 16:54

danke für die Hilfe...
habe es jetzt soweit mit mehreren regex hinbekommen...

das mit pyparsing kannte ich noch gar nicht :)

jetzt habe ich ein weiteres Problem das aber einfacher ist:

ich habe folgende strings:

st = "\n WORT"
st2 = "\n$ WORT"
st3 = "\n $ WORT"

Matchen soll der regex nur auf st !!!
Also wenn zwischen \n und WORT KEIN! Buchstabe auftritt...

hoffentlich kann mir jemand helfen...danke
Mati
User
Beiträge: 68
Registriert: Dienstag 6. Juni 2006, 16:54

Hallo
vielleicht ist dashier besser zu verstehen:
ich will auf einen string matchen in dem alle empty spaces erlaubt sind AUSSER \n Zeilenumbrüche
also:
st1 = "ich \n hier " <- kein match
st2 = "ich bin hier" <- match

Danke euch
BlackJack

Dazu braucht man keinen regulären Ausdruck:

Code: Alles auswählen

if '\n' not in string:
    # match
else:
    # no match
Antworten