Scripting: Gebe Text zwischen zwei Strings mit Sonderzeichen aus

Hallo. Ich suche und probiere schon sehr lange, bekomme es aber nicht hin und vermute es liegt an den speziellen Sonderzeichen, warum ich bisher keinen Erfolg hatte.

Ich habe eine Seite im LAN per curl in eine Datei test.txt geschrieben und möchte bestimmte Informationen extrahieren.

Ich möchte aus einer Datei test.txt aus folgendem Text:
encoding="utf-8"?> <Information><Audio><SoundMode>Dolby Audio - Dolby Surround</SoundMode><InputSignal>PCM</InputSignal><SampleRate>48 kHz

Als Ausgabe
Dolby Audio - Dolby Surround

erhalten.

Ich habe viele Beispiele aus ähnlichen Fällen mit meinen Strings ersetzt aber es hat bisher nicht funktioniert.

Ich würde das gerne mit grep oder sed machen.
Entschuldigt wenn die Antwort eigentlich banal ist aber ich bin Laie und wirklich nur sehr selten dabei scripts zu schreiben.

Bitte helft mir, sonst werde ich noch wahnsinnig :wink:

Danke

Hallo,

dieser reguläre Ausdruck sollte eigentlich passen:

\<SoundMode\>(.*?)\<\/SoundMode\>

Gruß,
Steve

Hi!

Das geht z.B. so:

grep -P -o "(?<=\<SoundMode\>).*(?=\</SoundMode\>)" MyFile.txt

-P: Verwende Pearl-RegularExpressions - nur die können „LookAround“

-o: Nur das Gesuchte ausgeben, nicht die ganze Zeile

(?<=\<SoundMode\>): Vor dem zu findenden String soll <SoundMode> stehen, es gehört aber selbst nicht zum Treffer. („LookBefore“) Die eckigen Klammern müssen aber escaped werden.

.* finde beliebig viele Zeichen

(?=\</SoundMode\>) Danach muss </SoundMode> kommen, das selbst nicht zum Treffer gehört. („LookAfter“) Auch hier wieder eckige Klammern.

Insgesamt sucht das also nach dem Text zwischen <SoundMode> und </SoundMode>. Achtung: Das muss alles in einer Zeile gefunden werden!

@Steve:

Mit deinem Ausdruck wird <SoundMode> und </SoundMode> ebenfalls ausgegeben. grep kennt wohl keine Gruppen, und kann daher nicht nur die durch die runden Klammern definierte Gruppe anzeigen.

Genau das habe ich auch probiert. Jetzt wo ich mir die txt genau anschaue merke ich, dass „“ und " mindestens 2 x vorhanden sind. Daher auch mein Problem, dass es so nicht funktioniert hat. Ich versuche nun (google) ganz pragmatisch alles was auf ein bestimmtes Wort folgt einfach zu löschen, bevor ich mit grep suche.

Kannst du das Problem etwas genauer erläutern? Irgendwie ist mir das nicht klar.

Gern.
Also ich habe mit wget den Quelltext eines ajax-request an das Webfrontend in eine Datei gespeichert. Daraus möchte ich per Skript Informationen (Eingangssignal, Trägerofrmat, Kanäle etc) auslesen.

Das Problem war die ganze Zeit, dass die Information SoundMode zwei mal auf der Seite angezeigt wird, also nicht nur einmal im Quelltext steht.

Mit der grep Abfrage
grep -P -o "(?<=\<SoundMode\>).*(?=\</SoundMode\>)" MyFile.txt
wird der Text zwischen dem ersten Treffer von <SoundMode> und dem letzten Treffer von </SoundMode> ausgegeben.

Wie ich Eingangs bereits erwähnte, kenne ich mich eigentlich nicht aus. Ich weiß z. B. nicht, wie ich grep mitgebe, dass jeweils nur die ersten Treffer verwendet werden sollen. Daher habe ich die ursprüngliche Datei mit dem gesamten Quelltext per sed ab einem bestimmten Wort des Quelltextes, das erst nach meinen benötigten Infos auftaucht, gekürzt.
sed -i.bak 's/Video.*//g' MyFilet.txt && rm MyFile.txt.bak
Damit habe ich das Problem mit mehrfachen Treffern gelöst.
Ich hoffe das war nun verständlich.

Ah, verstehe.
Dann wäre meine Lösung

grep -P -o "(?<=\<SoundMode\>).*?(?=\</SoundMode\>)" MyFile.txt

Die Sache ist, dass .* so viele Zeichen wie irgend möglich in Besitz nimmt. gesucht wird also der längsmögliche Text, der zwischen einem <SoundMode> und einem </SoundMode> gefunden werden kann. Wenn du mehrere solcher Einträge hast, dann wird wirklich alles zwischen dem ersten <SoundMode> und dem letzten </SoundMode> gefunden.

Mit .*? werden so wenige Zeichen wie möglich gefunden,also hier alles zwischen einem <SoundMode> und dem nächsten darauf folgenden </SoundMode>
Ich weiß grade nicht, ob grep dann auch wirklich mehrere Zeilen ausgibt.

Regular Expressions sind Fluch und Segen zugleich.
Man muss sie erstmal grundsätzlich verstehen, dann sind sie ein sehr mächtiges Werkzeug. Der Weg bis zum Schwarzen Gürtel ist aber ungefähr genauso lang wie bei Karate. Fremde RegEx-Ausdrücke sind auch nicht immer einfach zu verstehen, oder würdest du erkennen, dass das hier

([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5]) 

valide IP-Adressen findet, also z.B. 192.168.257.123 NICHT?

Genau solche Codezeilen finde ich häufig bei meinen Recherchen, wenn ich nicht weiter weiß - meist in Verbindung mit sed und awk. Ich verwende Sie jedoch nicht, da ich diese nicht verstehe. Es ist einfach zu kryptisch für mich, es irgendwie herzuleiten und so kann ich diese Beispiele auch nicht verwenden, da ich sie natürlich immer auf mein Vorhaben ändern muss. Und dann behelfe ich mir halt mit anderen Wegen, die ich jedoch verstehe. :wink:

Ich danke Dir. deine Lösung funktioniert.

Dieses Thema wurde automatisch 30 Tage nach der letzten Antwort geschlossen. Es sind keine neuen Nachrichten mehr erlaubt.