Seite 1 von 1

RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Dienstag 26. Dezember 2017, 22:16
von luvlinux
Guten Abend,

da ich mich derzeit mit RegEx-Gruppierung beschäftige wollte ich Foglendes lösen. Aus einem String Jahreszahlen aus den 1900ern und 2000ern heraussuchen. Ich sage also meinem Suchmuster, dass es nach 19 oder 20 mit 2 Zahlen anschließend suchen soll. Hier mein Code:

Code: Alles auswählen

import re
pattern = '(19|20)\d{2}'
string = '2014, 3143, 1923, 3143'
print(re.findall(pattern, string))
Als Ergebnis erhalte ich

Code: Alles auswählen

['20', '19']
Eigentlich habe ich mit ['2014', '1923'] gerechnet. Wo liegt den mein Fehler und wie schaffe ich es auf mein gewünschtes Ergebnis?
Danke schon jetzt für eure Hilfe.

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Dienstag 26. Dezember 2017, 22:47
von Sirius3
@luvlinux: Du bildest eine Gruppe nur über die ersten beiden Ziffern. Lösung: die Gruppe über alle Ziffern, oder gar keine Gruppe. Dein Ausdruck ist aber in sofern falsch, dass auch aus 31983 oder 20134 die vier Ziffern gefunden werden.

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Dienstag 26. Dezember 2017, 23:03
von snafu
Anstelle des regulären Ausdrucks lassen sich auch Python-Boardmittel verwenden:

Code: Alles auswählen

text = '2014, 3143, 1923, 3143'
for year in map(int, text.split(',')):
    if 1900 <= year < 2100:
        print(year)

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Mittwoch 27. Dezember 2017, 01:26
von pixewakb
Funktioniert aber nur, wenn es ein schöner String ist. In anderen Fällen ("Im Jahr 1996..."), also wenn der String auch Wörter enthält, funktioniert es nicht mehr.

Ich habe mal folgendes versucht und das Tool eingesetzt:

Code: Alles auswählen

>>> string = "Im Jahr 1996 wird das 2010-Programm aufgesetzt. Es führt zu 3045 Abfragen und 11945 Ergebnissen."
>>> re.findall("\d+", string)
['1996', '2010', '3045', '11945']
>>> re.findall("19\d{2}|20\d{2}", string)
['1996', '2010', '1945']
Ich würde - falls dein Problem komplex ist, wie ich es vermute - mittels re.findall("\d+", string) alle Zahlen suchen lassen und da - meine zweite Variante auch viele Falsch-Positive liefert (11945 -> 1945 :( ) - dann mit dem Vorschlag von snafu filtern. So könnte es gehen.

Vielleicht hat noch jemand eine Idee...

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Mittwoch 27. Dezember 2017, 07:42
von snafu
pixewakb hat geschrieben:Ich würde - falls dein Problem komplex ist, wie ich es vermute - mittels re.findall("\d+", string) alle Zahlen suchen lassen und da - meine zweite Variante auch viele Falsch-Positive liefert (11945 -> 1945 :( ) - dann mit dem Vorschlag von snafu filtern.
Diesen Vorschlag unterstütze auch ich. Reguläre Ausdrücke sind ganz gut, um Tokens zu finden (z.B. Wörter ohne die Satzzeichen oder Zahlen mit einer oder mehreren Ziffern). Die genauere Bedeutung solcher Fundstücke (hier: Bereich, in dem die Zahl liegt) prüft man besser mit den Möglichkeiten der Programmiersprache. Denn da stoßen reguläre Ausdrücke an ihre Grenzen: Es wird kompliziert bis unmöglich, damit alle Fälle abzudecken.

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 10:14
von luvlinux
Hallo zusammen,

vielen Dank für eure ausführlichen Antworten.
Ein Zusammenspiel zwischen den regex und Python-Programmierung ist wohl der beste Lösungsansatz. Ich werde mit diese Kombination mal noch etwas experimentieren.

Wünsche euch allen noch einen guten Rutsch und bis bald.

Jonathan

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 13:08
von ruedi_br
Im Beispielcode von pixewakb würde ich anstelle von "\d+" nach "\d\d\d\d" suchen, dann sollte 11945 herausfallen. lt. Hilfe sollte auch \d{4} tun, habe ich aber nicht probiert :|

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 13:21
von pixewakb
M. E. nein:

Code: Alles auswählen

>>> import re
>>> string = "Im Jahr 1996 wird das 2010-Programm aufgesetzt. Es führt zu 3045 Abfragen und 11945 Ergebnissen."
>>> re.findall("\d{4}", string)
['1996', '2010', '3045', '1194']

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 14:06
von __deets__
Kann man reparieren:

Code: Alles auswählen

re.findall("(?:[^\d]|^)(\d{4})(?:[^\d]|$)", string)

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 17:36
von luvlinux
@__deets__

Das klappt ja super. Ich versuche jetzt mal deine regex zu verstehen:
Du suchst also zuerst nach einem Nicht-digit [^\d]. Damit dieses nicht als Ergebnis erfasst wird, verwendest du ?:
Dann nach 4 digits hintereinander \d{4} anschließend wieder nach einem Nicht-digit, der wiederum mit ?: vom Ergebnis ausgeschlossen wird.

Liege ich soweit richtig? Bzw. was ich aber nicht verstehe ist das erste Oder ( ...|^) und das zweite Oder ( ...| $). Kannst du mir hier nochmals auf die Sprünge helfen?

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 17:48
von __deets__
So weit richtig. Allerdings würde ohne ^ bzw $ eine Zahl ganz am Anfang bzw Ende nicht gefunden werden. Genau diese Fälle decken die veroderungen ab.

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Donnerstag 28. Dezember 2017, 19:28
von luvlinux
Oki doki,

dann scheine ich es ja jetzt gerafft zu haben :D

Thx nochmals.

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Samstag 30. Dezember 2017, 00:57
von snafu
Was spricht denn gegen dies?

Code: Alles auswählen

numbers = map(int, re.findall(r'\d+', text))
years = [year for year in numbers if 1900 <= year < 2100]

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Samstag 30. Dezember 2017, 01:20
von Sirius3
@__deets__: das Gegenteil von »\d« ist »\D«:

Code: Alles auswählen

re.findall(r"(?:\D|^)(\d{4})(?:\D|$)", string)
Klarer was gemeint ist, wird es durch negativen look behind und look ahead:

Code: Alles auswählen

re.findall(r"(?<!\d)\d{4}(?!\d)", string)
kann man jetzt natürlich noch mit der Jahrhundertsuche verknüpfen:

Code: Alles auswählen

re.findall(r"(?<!\d)(?:19|20)\d{2}(?!\d)", string)

Re: RegEx - Suche nach Jahreszahlen liefert nur 2stelliges Ergebnis

Verfasst: Samstag 30. Dezember 2017, 01:49
von __deets__
@snafu Es spricht nix „dagegen“. Es löst ja das Problem. Wenn man aber eh schon rexe drin hat, dann halt richtig. Sonst mach einfach split & int(), und fang den ValueError ab.