ubuntuusers.de

Teilstring per sed extrahieren

Status: Gelöst | Ubuntu-Version: Ubuntu 19.10 (Eoan Ermine)
Antworten |

pacmexx

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

Hallo, kann mir bitte jemand zeigen wie so etwas geht. Zip-Dateien wurden mit Namen erstellt und im Nachgang umbenannt. Zur weiteren Verarbeitung per Script benötige ich jedoch den ursprünglich verwendeten Namen bei Erstellung der Datei (zip -sf). Die Ausgabe enthält weit mehr als ich benötige und möchte deshalb den relevanten Teilstring extrahieren. (wollen vs. können ☺)

# Ermitteln ursprl. Dateiname bei Erstellung der zip-Datei / FileStr=$(zip -sf $*)
FileStr="Archive contains: BlaBlupp.img Bla bla bla"
ContrStr='sed -r s/vodoo/magic' < $FileStr
echo $ContrStr ---> BlaBlupp.img

Gruß pac

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

pacmexx schrieb:

Hallo, kann mir bitte jemand zeigen wie so etwas geht. Zip-Dateien wurden mit Namen erstellt und im Nachgang umbenannt. Zur weiteren Verarbeitung per Script benötige ich jedoch den ursprünglich verwendeten Namen bei Erstellung der Datei (zip -sf). Die Ausgabe enthält weit mehr als ich benötige und möchte deshalb den relevanten Teilstring extrahieren. (wollen vs. können ☺)

# Ermitteln ursprl. Dateiname bei Erstellung der zip-Datei / FileStr=$(zip -sf $*)
FileStr="Archive contains: BlaBlupp.img Bla bla bla"
ContrStr='sed -r s/vodoo/magic' < $FileStr
echo $ContrStr ---> BlaBlupp.img

Ich hab's nicht verstanden, aber 2 Mindeständerungen meine ich trotzdem empfehlen zu können.

  • Sed: Der Substituionsbefehl geht "s/foo/bar/" also mit abschließendem Slash für den Ersatztext. Eventuell dahinter ein 'g', wenn mehr als eine Ersetzung pro Zeile stattfinden soll (soweit möglich).

  • Das Ergebnis eines Befehls weist man so einer Variablen zu: foo=$(befehl bla fasel). Apostrophe haben da nichts verloren, erst recht nicht ohne die Dateiumleitung zu umfassen.

ContrStr=$(sed -r s/vodoo/magic/ < $FileStr)

Je nach Inhalt von voodoo und magic wirst Du doppelte Anführungsstriche um den Befehl für sed benötigen, vielleicht auch einfache.

ContrStr=$(sed -r "s/vodoo/magic/" < $FileStr)

Jetzt sehe ich, dass $FileStr einen Text mit Leerzeichen enthält, womöglich keinen Dateinamen. Wäre es ein Dateiname in dem Text steht, der von Sed verarztet werden soll, dann wäre es aber:

ContrStr=$(sed -r "s/vodoo/magic/" "$FileStr")

denn Sed erwartet quasi, dass man ihm Dateien nennt, die zu bearbeiten sind. Will man aber den Inhalt der Variablen selbst modifizieren, dann geht es so:

ContrStr=$(echo "$FileStr" | sed -r "s/vodoo/magic/") 

pacmexx

(Themenstarter)

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

user_unknown schrieb:

denn Sed erwartet quasi, dass man ihm Dateien nennt, die zu bearbeiten sind. Will man aber den Inhalt der Variablen selbst modifizieren, dann geht es so:

ContrStr=$(echo "$FileStr" | sed -r "s/vodoo/magic/") 

Ja, Danke - schon mal ein Teil, was mir jedoch noch fehlt ist die Regex womit ich den Teilstring extrahiere, den aus

"Archive contains: BlaBlupp.img Bla bla bla"

soll werden

"BlaBlupp.img"

Also von Anfang des Strings muss "Archive contains: " und nach ".img" bis zum Ende des Strings " Bla bla bla" verschwinden.

pac

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13216

1
2
$ echo "Archive contains: BlaBlupp.img Bla bla bla" | sed -ne 's/^Archive contains: \(.*\.img\).*$/\1/p'
BlaBlupp.img

Wenn denn die Dateien immer auf ".img" enden.

pacmexx

(Themenstarter)

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

rklm schrieb:

1
2
$ echo "Archive contains: BlaBlupp.img Bla bla bla" | sed -ne 's/^Archive contains: \(.*\.img\).*$/\1/p'
BlaBlupp.img

Wenn denn die Dateien immer auf ".img" enden.

Ja, so funktioniert das

FileStr=$(zip -sf $*)   <--- "Archive contains: BlaBlupp.img Bla bla bla"
ContrStr=$(echo $FileStr | sed -ne 's/^Archive contains: \(.*\.img\).*$/\1/p')
echo $ContrStr          ---> "BlaBlupp.img" 

Jetzt habe ich das hier nochmal ein wenig aufgelöst, interpretiere ich das so richtig?

-ne    -->  --quiet, --expression=script
s      -->  substitute
^      -->  von Anfang der Zeile an
\(     -->  Klammerzeichen ( maskieren
.*     -->  BlaBlupp 
\.img  -->  maskieren ?
\)     -->  Klammerzeichen ) maskieren
.*$    -->  von da alles bis zum Ende des Strings
\1     -->  ?
/p     -->  Print the current pattern space ?

Danke+Gruß pac

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Wohnort: Göttingen

Also das \1 ist das, was zwischen den runden Klammern als Match gefunden wird. Vielleicht zur Verdeutlichung:

$ echo hallo du da | sed -ne 's/^\([a-z]*\) \([a-z]*\) \([a-z]*\)/\1/p'
hallo
$ echo hallo du da | sed -ne 's/^\([a-z]*\) \([a-z]*\) \([a-z]*\)/\2/p'
du
$ echo hallo du da | sed -ne 's/^\([a-z]*\) \([a-z]*\) \([a-z]*\)/\3/p'
da

Hoffe, damit ist das klarer geworden.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13216

Genau. Die Klammer wird nicht maskiert, sondern durch den vorangestellten Backslash zu einem Meta-Zeichen, das Beginn und Ende einer Gruppe markiert.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

pacmexx schrieb:

Jetzt habe ich das hier nochmal ein wenig aufgelöst, interpretiere ich das so richtig?

-ne    -->  --quiet, --expression=script
s      -->  substitute
^      -->  von Anfang der Zeile an
\(     -->  Klammerzeichen ( maskieren
.*     -->  BlaBlupp 
\.img  -->  maskieren ?
\)     -->  Klammerzeichen ) maskieren
.*$    -->  von da alles bis zum Ende des Strings
\1     -->  ?
/p     -->  Print the current pattern space ?

Ja. Der unmaskierte Punkt steht für ein beliebiges Zeichen. Aber .*$ nicht bis Ende des Strings sondern bis Zeilenende. Das e in -ne kannst Du weglassen. Ein Beispiel, wo man das nicht kann ist, wenn man mehrere Befehle getrennt eingibt:

1
sed -e "foo" -e "bar" -e "baz" FILE

Mit etwas sinnvollem in foo, bar, baz.

Und \1 ist das erste von einem Klammernpaar umschlossene Pattern. Die Maskiererei der Klammern kann man sich mit -r sparen was immer dann bequem ist, wenn der Ausdruck nicht literale runde Klammern enthält, die dann stattdessen maskiert werden müssten. Rklm widerspreche ich daher bezüglich der Terminologie. Maskieren ist das Verfahren auf der Ebene der Zeichensetzung. Das Ziel der Maskierung ist die Erzwingung der Interpretation als Metazeichen.

pacmexx

(Themenstarter)

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

Danke für die Infos, bis zum nächsten Problem mit awk und sed.

Gruß pac

Antworten |