• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] regulärer Ausdruck in Stringkonstante

utopos

Member
Hallo zusammen,

ich suche einen Befehl, der überprüft, ob eine gegebene Text-Konstante auf einen ebenfalls gegebenen regulären Ausdruck passt.
Also etwa:
Code:
passt *ende* wende
soll Exit-Status 0 ergeben,
Code:
passt *ende* Endstück
hingegen Exit-Status >1.
Soweit ich weiß, suchen grep und Konsorten ja stets in Dateien und nicht in der Standardeingabe.

Kennt Ihr da etwas?
 
OP
U

utopos

Member
Alles klar. Ich wusste, dass Pipes eine Rolle spielen, hatte aber die ''' vergessen.

Kannst Du mir sagen, warum

Code:
echo 'hallo' | grep '*al*'

keinen Treffer (also Exit-Status = 0) liefert?
 
A

Anonymous

Gast
utopos schrieb:
Kannst Du mir sagen, warum
Code:
echo 'hallo' | grep '*al*'
keinen Treffer (also Exit-Status = 0) liefert?
weil vor dem "a" in "hallo" kein "*" ist und hinter dem ersten "l" auch nicht.
Code:
echo "h*al*lo" | grep '*al*'
ansonsten mal in die Manpage von grep schauen, da steht einiges zu Regulären Ausdrücken unter anderem auch
* The preceding item will be matched zero or more times.
Ansonsten ist das Internet voll davon.
eventuell auch mal
Code:
echo 'hallo' | egrep '*al*'
probieren und staunen
Dein Beispiel Regulärer Ausdruck sucht nach" "NICHTS das vorhanden sein kann und sich beliebig oft wiederholt darf????? (philosofisch gesehen; wenn NICHTS beliegig oft vorkommen kann, dann ist eine bestimmte Menge von NICHTS aber doch irgendwas) , anschließend einem "a" und daran gefolgend "l" das vorhanden sein kann (aber nicht muss) und sich auch noch beliebig wiederholen darf."

Also suchst du mehr oder weniger alle Wörter mit mindestens einem "a" ???????????

robi
 
OP
U

utopos

Member
Vielen Dank soweit - ich weiß jetzt, was ich in meinem Fall machen kann.

Aber auch aus den umfangreichen Dokumentationen, die ich auch vor dem Fragen hier gelesen hatte, wird mir nicht klar, warum
Code:
echo hallo | grep ha*o
genauso wie
Code:
echo hallo | egrep *allo
zu dem erwarteten Treffer führt, nicht aber
Code:
echo hallo grep *allo

Sind Sterne und Fragezeichen am Rande des Suchstrings bei grep einfach ausgeschlossen?
 
A

Anonymous

Gast
utopos schrieb:
Sind Sterne und Fragezeichen am Rande des Suchstrings bei grep einfach ausgeschlossen?
nein sie geben nur sehr oft unberechenbare Ergebnisse ;) Weil derjenige dort überhaupt nicht weiß was er da überhaupt für einen Befehl lostritt.

es macht zB einen riesen Unterschied ob ich den ersten den 2. oder den dritten der folgenden Befehle ausführe.
Code:
ls | grep a*
ls | grep "a*"
ls | grep -F "a*"

beim ersten Befehl wird eventuell schon die Bash im aktuellen Verzeichnis alle Dateien suchen die mit "a" beginnen und diese bei Start an dem Befehl grep anhängen. Ergebnis: gibt es solche Dateien dann wird der erste Dateiname als Such-Argument für grep gewertet und alle weiteren Dateinamen sind dann Argumente für grep in denen es nach dem ersten Dateinmane sucht. Je Komandozeilenaufbau und Inhalt des aktuellen Verzeichnisses wird entweder das Falsche in falschen Dateien gesucht, es kommen Fehlermeldungen die mit dem Befehl scheinbar nichts richtiges zu tun haben, oder es kommt zum komplette Fehler in der Komandozeile. Das gesamte Ergebniss ist von vielen Faktoren abhängig unter anderem welche Dateien du im aktuellen Verzeichnis hast. Ein vernünftiges Ergebnis wirst du jedenfalls nie bekommen. Ist diese * jetzt nicht am Ende des Suchstrings sondern vielleicht in der Mitte oder am Anfang, dann wird die Bash das beim Aufrufen eventuell aber auch nicht zu Dateinamen interpretieren können (Wahrscheinlichkeit von Treffern im Filesystem ist kleiner) und es wird dann von grep als regulärer Ausdruck gewertet, Das Ergebnis ist aber wiederum von dem gesamten Komandozeilenaufbau und der Dateien im aktuellen Verzeichnis abhängig und mehr oder weniger zufällig richtig oder total daneben.
Die Arbeitsweise von Grep ist dabei immer gleich, allerdings durch den Shellaufruf werden ganz andere Grepoptionen gestartet. Schuldig an falschen Ergebnissen ist also die Shell (besser der, den den Befehl absetzt) und nicht grep. In dieser Beispielgruppe würdest du hier zB sofort sehen warum grep dir widererwarten keine oder total falsche Ergebnisse liefert, wenn du mal die Option -v probierst und nachschaust was er überhaupt durchsucht.

beim zweitem Befehl wird das "a*" jetzt als Regulärer Ausdruck interpretiert. und dort bedeutet ein * :
das im Ausdruck davor befindliche (oder beschriebene) Zeichen kann null bis unendlich viele Male hintereinander vorkommen.
Das Ergebnis hier ist es werden alle Dateien gefunden ob sie jetzt ein a haben oder auch nicht.
Code:
ls | grep  "l*st*"
würde also alles finden was ein s hat und nicht nur "list last2 lustig" usw.
Und selbst da gibt es noch Unterschiede zwischen grep "irgendwas" und grep 'irgendwas' das würdest du spätestens merken wenn in irgendwas mal ein "$" enthalten ist. Auch hier könnte die Shell bei "irgendwas" noch grep Optionen ändern.


Beim dritten Befehl wird nun das "a*" wort-wörtlich genommen und wirklich nach einer Datei gesucht die hinter einem a einen * hat.

Der * und das ? wie du sie verwenden willst, sind Substitutionszeichen der Shell die beim Programmaufruf eine Rolle spielen. Die Shell wird sie eventuell auch beim Programmaufruf interpretieren wenn du die Shell nicht durch Quotas davon abhältst. Eventuell auch nicht, oder es wird dort nichts passendes gefunden. Das geht aber ganz anders vonstatten als man es gemeinhin denkt, die Shell macht aus "*" zB plötzlich eine ganze Liste von einzelnen Dateinamen des aktuellen Verzeichnisses die alle anstatt des einzelnen * an den aufzurufenden Befehl übergeben werden.

Das * ist aber auch ein Bestandteil in fast allen Versionen von Regulären Ausdrücken hat aber dort eine ganz andere Bedeutung. Somit ist ein * am Anfang eines Regulären Ausdruckes eigentlich ein logischer Fehler im Regulären Ausdruck selbst, der allerdings meist nicht als Fehler gemeldet wird, sondern entweder ignoriert wird und der Rest bleibt dann als Regulärer Ausdruck aktiv, oder aber und genau das scheint oben bei ".echo 'hallo' | grep '*al*'" zu passieren, grep erkennt das ist überhaupt kein gültiger Regulärer Ausdruck und selbständig den Suchmodus auf "--fixed-strings" umschwenkt und wirklich dann genau so sucht wie in Beispiel 3.

Ein * wie du es wahrscheinlich verwenden willst, müsstest du im Regulären Ausdruck mit ".*" schreiben
Das ? ist etwas einfacher, würde im Regulären Ausdruck einem "." (Punkt) entsprechen.
Das bedeutet aber
Code:
ls | grep "list.txt"
findet auch solche Dateinamen die sonst passen aber anstatt des Punktes an dieser Stelle ein ganz anderes Zeichen steht.

Mit Regulären Ausdrücken muss man sich ein paar Stunden intensiv befassen, danach muss man dann sehen wie die einzelnen Programme und Tools mit all den Sonderzeichen in der Komandozeile umgehen und dann muss an überlegen wie man diese dann so verstecken oder entwerten kann, das sie vom aufrufenden Programm nicht schon falsch verstanden werden und somit falsch oder gar nicht dort ankommen wo man sie braucht. Letztlich hilft immer nur ein Test. Bei grep sollte dieser immer recht gründlich gemacht werden, damit man keine böse Überraschung erlebt.

Erschwerend bei grep kommt noch hinzu, das auch eventuell Umgebungsvariablen die Funktion von grep beeinflussen könnten. In der Praxis wird man entweder saubere Reguläre Ausdrücke verwenden, oder Sonderzeichen in Suchausdrücken bei grep möglichst immer vermeiden und ansonsten mit nicht ganz 100%richtigen Suchausdrücken meist auch das finden, was man sucht, weil eben in den duchsuchten Daten keine weiteren Alternativen sind, die auch von grep gefunden werden würden. Man sollte sich also nicht täuschen lassen, wenn man als Linuxneuling mal so in den ersten 2 Stunden auf der Linuxkonsole mit grep wirklich die paar Zeilen in der Datei gefunden hat, die man wirklich suchen wollte. Solche ersten positiven Erfahrungen sollte man nicht versuchen daraufhin zu deuten das man jetzt grep verstanden hat oder gar es beherrscht. ;) Grep ist in seiner Gesamtheit komplex, kompliziert und auch nach Jahren der regelmäßigen Benutzung des Befehls immer wieder für Überraschungen gut.

robi
 
Hallo robi,
das ist ja mal ein Hammer Beitrag. Respekt!
Jaja grep ist so umfangreich das man sich schon sehr intensiv beschäftigen muss wenn das Ergebnis auch richtig sein soll.
Folgende Formel verwende ich hier:
Code:
IFS=$'\n'; for file in *.mp3; do if [[ ${file} =~ ^[0-9] ]]; then mv ${file} $(echo ${file} | sed 's/^[[:digit:]]\+-\?//'); fi; done
Ich habe Verzeichnisse mit Dateien die alle folgendem Suchmuster entsprechen:
001_Textteil1.-Textteil2.ext
002_Textteil1.-Textteil2.ext
002_Textteil1.-Textteil2.ext
003_Textteil1.-Textteil2.ext
004_Textteil1.-Textteil2.ext

mit Hilfe obiger Formel werden die Ziffern und der Unterstrich aus den Dateien entfernt und diese mit dem neuen Dateinamen geschrieben. Das funktioniert aber nur wenn die zahlentf.sh (so hab ich die genannt) im Verzeichnis liegt wo die Dateien auch liegen. In einem Pfad kämen dann die Pfad-Trenn-Zeichen / als Suchbegriff hinzu und müssten auf den jeweiligen Pfad abgestimmt werden.

Zum Einsatz kommt hier statt des grep der sed, was aber mindestens ebenso komplex ist (Zumindest für mich)
Das "schlimme" ist halt das grep auch nach den vermeintlichen Wildcards als Zeichen sucht, ergo müssen diese durch entsprechende Hochkommata " oder `oder ' ausgeklammert werden.
Ich bin noch dabei mir das Buch "grep - kurz und gut" durchzulesen...bis das sitzt dauert noch.
lieben Gruß aus Hessen
 

abgdf

Guru
Könnte mir vorstellen, daß bash und grep bei "*" durcheinanderkommen. Wenn's wirklich detaillierte Suchen sind, würd' ich's in Perl (oder einer anderen Sprache (Python, awk)) angehen: Da hat man mehr Kontrolle und auch keine Konflikte mit bash.

Gruß
 
Oben