Frage zu sed Kommando

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

Frage zu sed Kommando

Beitrag von fiberkill » 05.08.2014 07:39:13

Hallo zusammen,
ich habe in kleines Problem mit sed.
ich habe eine Textdatei und möchte darin mehrere Zeilen, die so aussehen:

*Intern, eingabe=../../../01_KOMPONENTEN_EXP/Dateiname_0.inf
*Intern, eingabe=../01_KOMPONENTEN_EXP/Dateiname_1.inf
*Intern, eingabe=../../../01_KOMPONENTEN_EXP/Dateiname_2.inf


in folgende ändern:

*Intern, eingabe=Dateiname_0.inf
*Intern, eingabe=Dateiname_1.inf
*Intern, eingabe=Dateiname_2.inf

Das soll durch die gesamte Datei erfolgen.

So wie ich das sehe, müsste man Zeile für Zeile den Inhalt überpüfen und wenn die Zeile mit "*Intern, eingabe=" beginnt, alles zwischen dem "=" und inklusive dem letzten "/" löschen.
Leider sind meine sed Kenntnisse nicht besonders und darum möchte ich Euch um Hilfe bitten.

Besten Dank im Voraus.

Gruss fk

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Frage zu sed Kommando

Beitrag von Cae » 05.08.2014 08:03:06

Code: Alles auswählen

$ cat >testdata
*Intern, eingabe=../../../01_KOMPONENTEN_EXP/Dateiname_0.inf
*Intern, eingabe=../01_KOMPONENTEN_EXP/Dateiname_1.inf
*Intern, eingabe=../../../01_KOMPONENTEN_EXP/Dateiname_2.inf
$ sed 's@^\(\*Intern, eingabe=\)\(.*/\)\(.*$\)@\1\3@g' testdata 
*Intern, eingabe=Dateiname_0.inf
*Intern, eingabe=Dateiname_1.inf
*Intern, eingabe=Dateiname_2.inf
$ sed 's@^\*Intern, eingabe=.*/@\*Intern, eingabe=@g' testdata 
*Intern, eingabe=Dateiname_0.inf
*Intern, eingabe=Dateiname_1.inf
*Intern, eingabe=Dateiname_2.inf
$ 
Die erste Variante arbeitet mit Referenzen und ist vielleicht komplizierter zu verstehen. Die zweite Variante nimmt einfach den String, der mit *Int... am Zeilenanfang (^) beginnt und mit einem Slash / aufhoert (.*/, dabei expandiert .* auf alles, bis das letzte / erreicht wird), und ersetzt ihn komplett durch den statischen String *Int.... Dabei faellt der dynamische Teil zwischen = und dem letzten / weg.

Die Variante mit Referenzen addressiert jeden interessanten Teilausdruck ueber Klammern \(\), der entsprechende Inhalt kann auf der mittleren Seite von s/// (also bei b in s/a/b/c) per Nummern angesprochen werden, z.B. \3. Da ich nur den ersten und den dritten Ausdruck nehme und der dynamische Teil im zweiten Teilausdruck liegt, faellt er effektiv weg.

Falls du viele Zeilen hast, die nicht auf das Schema matchen, kann es vorteilhaft sein, einen Suchausdruck vorzuschalten. Dies ist effizienter, weil sed(1) dann erst gar nicht versucht, einen Ersetzungsbefehl durchzufuehren, der ohnehin nichts ersetzt. Dazu waere

Code: Alles auswählen

/^\*Intern, eingabe=/
voranzustellen, also in der Form

Code: Alles auswählen

$ sed '/^\*Intern, eingabe=/s@^\*Intern, eingabe=.*/@\*Intern, eingabe=@g' data
fuer das zweite Beispiel.

Achja, und * ist ein Sonderzeichen, was normalerweises fuer "vorhergehender Ausdruck in beliebiger Anzahl" stehen wuerde, z.B. wuerde aaaaaaa auf a* matchen. Daher muss er escapt werden, wobei das fuer diesen speziellen Fall nicht stimmt, weil das * am Anfang des Ausdrucks steht und es somit keinen Vorgaengerausdruck gibt (^ zaehlt in dem Zusammenhang nicht). Die escapte Variante schadet aber nicht und ist nachvollziehbarer.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

gelöst Re: Frage zu sed Kommando

Beitrag von fiberkill » 05.08.2014 08:54:28

Hi Cae

Vielen Dank.
Das war eine Punktlandung. Genau das hab ich gesucht.

Super.

Gruß FK

uname
Beiträge: 12403
Registriert: 03.06.2008 09:33:02

Re: Frage zu sed Kommando

Beitrag von uname » 05.08.2014 09:01:05

Auch wenn eine sed-Lösung gefordert wurde kann man es auch mit awk programmieren. awk bietet die Möglichkeit mehrere Trennzeichen zu verwenden. So kann man als Trennzeichen das Gleichheitszeichen und den Slash nutzen und dann einfach das erste und das letzte Feld durch ein Gleichheitszeichen getrennt ausgeben. Funktioniert aber nur solange man diese Vorgaben auch wirklich einhält. Aber ich glaube Slashes und Gleichheitszeichen (auch escaped) sind in Dateinamen nicht erlaubt und am Anfang ist sowieso alles fest vorgegeben.

Code: Alles auswählen

awk -F"=|/" '{print $1"="$NF}' testdata
*Intern, eingabe=Dateiname_0.inf
*Intern, eingabe=Dateiname_1.inf
*Intern, eingabe=Dateiname_2.inf

fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

Re: Frage zu sed Kommando

Beitrag von fiberkill » 07.08.2014 10:28:53

Vielen Dank an alle, die mir hier geholfen haben.
Ich hätte noch eine Frage:
wie kann ich mit sed oder awk eine Zeile in einem Textfile finden und ggf. löschen, die mit "**" beginnt?

Danke schon mal im Voraus.

Gruss FK

Benutzeravatar
ThorstenS
Beiträge: 2875
Registriert: 24.04.2004 15:33:31

Re: Frage zu sed Kommando

Beitrag von ThorstenS » 07.08.2014 10:39:54

Code: Alles auswählen

egrep -v "^\*" Eingabe > Ausgabe
oder
sed -i '/^\*/d' Datei

Benutzeravatar
Livingston
Beiträge: 1816
Registriert: 04.02.2007 22:52:25
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: 127.0.0.1

Re: Frage zu sed Kommando

Beitrag von Livingston » 07.08.2014 19:48:29

http://www.grymoire.com/Unix/sed.html hilft!
Wenn Du's durch hast, musst Du nicht mehr für jedes Standardproblem unter sed einen neuen Thread aufmachen.

Antworten