Seite 1 von 2

re

Verfasst: Mittwoch 4. Dezember 2019, 13:29
von Fire Spike
Hallo ich habe versucht mit re.search() etwas bestimmtes aus eine string ausgeben zu lassen, aber da mir re sehr neu ist weiss ich nicht wie ich es umsetzen soll.
Ich schreibe mal meinen string hier rein und markiere alles rot das ich nicht will und grün was ich ausgeben möchte.
"/bin/sh: 1: fff11&: not found"
könnte mir jemand helfen?

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 14:10
von sparrow

Code: Alles auswählen

text="/bin/sh: 1: fff11&: not found"
text.split(":")[-2].strip()

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 14:54
von Sirius3
@Fire Spike: wie sieht das Muster aus, das Du suchen willst? Nur so kann man einen regulären Ausdruck schreiben. Was sind alle möglichen Strings, die Du hast und was möchtest Du aus all denen extrahiert haben?

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 15:00
von __blackjack__
Ohne `re` unter der Annahme das die nicht gewünschten Anteile fest sind:

Code: Alles auswählen

In [1]: line = "/bin/sh: 1: fff11&: not found"                                  

In [2]: prefix = "/bin/sh: 1: "                                                 

In [3]: suffix = " not found"                                                   

In [4]: if line.startswith(prefix) and line.endswith(suffix): 
   ...:     print(line[len(prefix):-len(suffix)]) 
   ...:                                                                         
fff11&:
Wenn man das unbedingt mit `re` lösen möchte, müsstest Du mehr darüber erzählen was die Rahmenbedingungen sind, also was da in den roten und grünen Teilen variabel ist und nach welchem Muster(n) das varriieren kann, denn genau *das* muss man dann ja mit einem regulären Ausdruck formulieren.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 15:08
von Fire Spike
das grüne kann alles auf der Tastatur sein und auch jede länge haben, das rote ist immer das selbe.
Hilft das?

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 15:32
von __blackjack__
Na dann greift meine nicht-re-Lösung doch prima. Ein regulärer Ausdruck würde da keinen Gewinn bringen, wäre aber wirklich sehr simpel.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 15:55
von Fire Spike
ich habe gerade gemerkt das die blau markierte Zahl varieren kann. Sie kann zufällig sein, auch in der Länge.
"/bin/sh: 1: fff11&: not found"
Dann geht dein Script ja nicht mehr :roll:

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 16:22
von pillmuncher
Fire Spike hat geschrieben: Mittwoch 4. Dezember 2019, 15:55ich habe gerade gemerkt das die blau markierte Zahl varieren kann.
Naja, so schwer ist das auch nicht:

Code: Alles auswählen

>>> text="/bin/sh: 1: fff11&: not found"
>>> text.split(":")[0].strip()
'/bin/sh'
>>> text.split(":")[1].strip()
'1'
>>> text.split(":")[2].strip()
'fff11&'
>>> text.split(":")[3].strip()
'not found'
Oder ohne unnötige Wiederholungen:

Code: Alles auswählen

>>> parts = [s.strip() for s in text.split(":")]
>>> parts
['/bin/sh', '1', 'fff11&', 'not found']

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 16:30
von Fire Spike
Danke Pillmuncher könntest du vielleicht doch noch eine re lösung posten? Dann weiss ich wenigstens wie ich so etwas mit re lösen könnte ;)

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 16:33
von __blackjack__
@Fire Spike: Was hast Du denn bisher versucht? Und wie/womit? Schau Dir mal https://regex101.com/ an. Es gibt auch andere Online-Dienste und auch Desktopanwendungen um beim Entwickeln von regulären Ausdrücken zu helfen.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 18:55
von LeSchakal
@pillmuncher: Wenn im gesuchten Text allerdings ein Doppelpunkt vorkommt, ist die Lösung nicht mehr so ideal.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 20:56
von Fire Spike
@__blackjack__ danke für deinen link, aber wenn ich auf Python umstellen will wird alles Weiss und es passiert nichts mehr.
Ich versuchte bisher das:

Code: Alles auswählen

print(re.search(f"/bin/sh:[a-z+A-Z+0-9+{string.punctuation}] not found", "/bin/sh: 1: fff11&: not found"))
@LeSchakal das ist wirklich ein Problem.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 21:54
von __blackjack__
@Fire Spike: Die Seite verwendet JavaScript. Falls Du das blockierst müsstest Du es für die Seite freischalten.

Innerhalb von eckigen Klammern gelten in regulären Ausdrücken deutlich andere Regeln als ausserhalb. Und Du hast Glück das in `string.punctuation` vor dem "]" ein "\" steht, sonst wäre das syntaktisch kein korrekter regulärer Ausdruck. Der "\" hat eine besondere Bedeutung in regulären Ausdrücken auch innerhalb von eckigen Klammern, das heisst ein "\" selbst ist in dem Muster nicht enthalten. Und bei ",-." hast Du Glück, dass das gerade genau diese drei Zeichen beschreibt, denn auch das "-" hat eine besondere Bedeutung innerhalb von eckigen Klammern, die Du ja benutzt.

Problem ist, das der blaue Teil hier

/bin/sh:[a-zA-Z0-9+!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~] not found

für *genau* *ein* Zeichen steht. Und zwar eines aus der Zeichenmenge die innerhalb der eckigen Klammern beschrieben wird.

Das ist aber alles viel zu kompliziert. Warum willst Du da alle Möglichen Zeichen aufzählen? Kann es denn nicht *irgendein* Zeichen sein, und davon dann beliebig viele zwischen dem Prä- und dem Suffix‽ Das wäre *total simpel*.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 22:09
von Fire Spike
Ich habe nur alle aufgelistet weil ich nicht weiss wie ich es sonst machen soll und die beliebige länge weiss ich nicht wie ich es machen soll.:roll:
Ich habe versucht den AD Blocker und den Malwarebytes Browser Guard zu deaktivieren , leider hilft es nicht. Ich selbst blockiere kein Javascript.

Edit: Ich habe herausgefunden das ich ein "." für ein beliebiges Zeichen einsetzen kann, eine beliebige länge finde ich nicht.

Re: re

Verfasst: Mittwoch 4. Dezember 2019, 23:00
von snafu
Das re-Modul hat eine Online-Dokumentation: https://docs.python.org/3/library/re.html

Sucht man dort nach "any character", dann findet man folgendes:
(Dot.) In the default mode, this matches any character except a newline. If the DOTALL flag has been specified, this matches any character including a newline.
Somit muss man im regulären Ausdruck halt einen Punkt verwenden, um ein (nahezu) beliebiges Zeichen zu matchen. Für Wiederholungen mit mindestens einem Vorkommen benutzt man das Plus-Zeichen. Eine Kombination aus beidem lautet demnach .+. Wenn nichts mehr dahinter steht, dann trifft dies alles bis zum Zeilenende (ohne das abschließende \n). Andernfalls fügt man halt ein anderes Zeichen (oder Ausdruck) als Begrenzung ein. Aufpassen muss man in dem Zusammenhang mit dem Umfang des Treffers. Dazu solltest du dich mit den Stichwort "greedy" bzw "non-greedy" beschäftigen. Oft will man non-greedy als Verhalten haben und sollte somit ein Fragezeichen dahinter setzen, also in diesem Fall .+? schreiben, damit er nicht mehr als erwartet matcht.

Um jetzt z.B. Text innerhalb von Klammern zu finden, kann man folgendes nehmen:

Code: Alles auswählen

re.findall(r"\(.+?\)", text)
Den ersten Backslash braucht man zum Escapen, weil die öffnende Klammer sonst eine besondere Bedeutung hätte, was hier aber nicht gewünscht ist. Der zweite Backslash ist quasi freiwillig. Da kann man sich aussuchen, ob man alle Klammern escaped, wenn man tatsächlich die Klammer meint oder ob man das nur für die öffnenden Klammern so handhabt.

EDIT:
Wenn man wirklich nur an den Text will innerhalb der Klammern will, müsste man sogar innere Klammern setzen, um eine Gruppe zu definieren. Dann haben sie auch die besondere Bedeutung, die ich erwähnt hatte.

Code: Alles auswählen

re.findall(r"\((.+?)\)", text)
Und wenn man auch mit Klammern ohne Inhalt klar kommen will (kein Treffer), dann muss man es nochmals erweitern:

Code: Alles auswählen

re.findall(r"\(([^)]+)\)", text)
Wie man sieht, fangen reguläre Ausdrücke schon spätestens da an, so "richtig Spaß" zu machen...

Re: re

Verfasst: Donnerstag 5. Dezember 2019, 08:53
von Fire Spike
Vielen Dank snafu.
Ich konnte deinen Code noch anpassen und jetzt funkioniert es.

Code: Alles auswählen

print(re.findall(r"/bin/sh: (.+?): not found", string)[0].split(": ", 1)[1])

Re: re

Verfasst: Donnerstag 5. Dezember 2019, 09:14
von sparrow
Wenn du schon eine Regular Expression benutzt, die ich an dieser Stelle eh schon übertrieben finde, warum schränkst du das Ergebnis nicht gleich so weit ein, dass du hinterher nicht noch irgendwelche String-Operationen einsetzen musst? Dann kannst du es auch gleich über String-Operationen lösen.

Re: re

Verfasst: Donnerstag 5. Dezember 2019, 09:18
von snafu
Richtig. Der jetzige Ansatz ist wirklich sehr fragwürdig. Da sollte man eher die search() Funktion aus dem Modul nehmen und sich in dem Zusammenhang mal mit der group() Methode vertraut machen.

Re: re

Verfasst: Donnerstag 5. Dezember 2019, 10:00
von Fire Spike
So?

Code: Alles auswählen

re.search(r"/bin/sh(.+): (.+?): not found", string).group(2)

Re: re

Verfasst: Donnerstag 5. Dezember 2019, 10:28
von __blackjack__
@Fire Spike: Wenn Dich der Inhalt der ersten Gruppe nicht interessiert, dann mach da einfach keine Gruppe daraus. Und Du hast natürlich so ein Problem wenn in dem Teil den Du haben willst ein Doppelpunkt vorkommt. Und wenn da ": not found" ebenfalls.

Upsi, und `search` ist hier natürlich absolut falsch, Du willst ja nicht dass das Muster irgendwo innerhalb vorkommen kann, sondern dass das Muster tatsächlich die gesamte Zeichenkette beschreibt, also `fullmatch()`.