[gelöst] sed: Zeile isolieren und bearbeiten

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

[gelöst] sed: Zeile isolieren und bearbeiten

Beitrag von detix » 12.01.2008 14:45:37

Ich möchte nach dem 1. Auftreten meines Suchbegriffes die Weiterverarbeitung
der Datei beenden und nur die gefundene Zeile bearbeiten.
Warum funktioniert das nicht:
(in der 3. Zeile 'ccdcc' das d durch f ersetzen)

x="aabaa\nbbcbb\nccdcc\nddedd"
echo -e $x | sed -e '/ccdcc/q; $!d; s/d/f/'
Ausgabe: 'ccdcc'

mit
echo -e $x | sed -e '/ccdcc/q; $!d'
wird die Zeile zwar isoliert, aber die Weiterverarbeitung mit
s/d/f/
klappt nicht, warum?

Funktionieren tuts so:
echo -e $x | sed -e '/ccdcc/q; $!d' | sed -e 's/d/f/'
Ausgabe: 'ccfcc'

Kann mir das mal jemand erklären...
Zuletzt geändert von detix am 19.01.2008 22:25:01, insgesamt 1-mal geändert.
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: sed: Zeile isolieren und bearbeiten

Beitrag von Meillo » 12.01.2008 20:51:35

detix hat geschrieben:Ich möchte nach dem 1. Auftreten meines Suchbegriffes die Weiterverarbeitung
der Datei beenden und nur die gefundene Zeile bearbeiten.
Warum funktioniert das nicht:
(in der 3. Zeile 'ccdcc' das d durch f ersetzen)

x="aabaa\nbbcbb\nccdcc\nddedd"
echo -e $x | sed -e '/ccdcc/q; $!d; s/d/f/'
Ausgabe: 'ccdcc'

mit
echo -e $x | sed -e '/ccdcc/q; $!d'
wird die Zeile zwar isoliert, aber die Weiterverarbeitung mit
s/d/f/
klappt nicht, warum?
Aber das ist doch logisch, denn das Script macht genau was du sagst .... nur sagst du nicht das was du willst :-D

Du sagst: wenn 'ccdcc' gefunden wurde, soll beendet werden ... nun, das genau tut es.
Funktionieren tuts so:
echo -e $x | sed -e '/ccdcc/q; $!d' | sed -e 's/d/f/'
Ausgabe: 'ccfcc'

Kann mir das mal jemand erklären...
Dass es hier funktioniert liegt genau an dem was ich oben beschrieben habe: Das erste SED-Script wird abgebrochen nachdem 'ccdcc' gefunden und ausgegeben wurde. Danach wird die Ausgabe mit dem zweiten SED-Aufruf bearbeitet.


verstanden?
Use ed once in a while!

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 12.01.2008 21:15:23

Ich hab gerade kein Linux zur Hand, aber müsste nicht auch ein

Code: Alles auswählen

sed -e '/ccdcc/{s/d/f/;q;}'
funktionieren?

fuzzy
Beiträge: 1021
Registriert: 04.10.2003 12:15:52

Re: sed: Zeile isolieren und bearbeiten

Beitrag von fuzzy » 12.01.2008 22:41:22

detix hat geschrieben: echo -e $x | sed -e '/ccdcc/q; $!d' '
daraus würde ich folgendes machen:

Code: Alles auswählen

echo -e $x | sed '/ccdcc/!d' 
...und dann weitersehen bzw. weiterverarbeiten :wink:
Die Erklärung hatte Meillo genannt.

Gruß fuzzy

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: sed: Zeile isolieren und bearbeiten

Beitrag von Meillo » 13.01.2008 00:15:32

fuzzy hat geschrieben:
detix hat geschrieben: echo -e $x | sed -e '/ccdcc/q; $!d' '
daraus würde ich folgendes machen:

Code: Alles auswählen

echo -e $x | sed '/ccdcc/!d' 
Das funktioniert nicht, weil dadurch alle Vorkommen und nicht nur das erste ausgegeben werden.

Statt

Code: Alles auswählen

x="aabaa\nbbcbb\nccdcc\nddedd" 
könntest du auch

Code: Alles auswählen

x="aabaa
bbcbb
ccdcc
ddedd" 
verwenden, dann brauchst du kein '-e' bei echo.

Joghurt hat geschrieben:Ich hab gerade kein Linux zur Hand, aber müsste nicht auch ein
Code:
sed -e '/ccdcc/{s/d/f/;q;}'
funktionieren?
guter Tipp!

Ich komme zu folgender Lösung:

Code: Alles auswählen

echo -e $x |  sed -n '/ccdcc/{s/d/f/; p; q;}'
Use ed once in a while!

Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Beitrag von detix » 13.01.2008 11:03:44

Also, wenn ich das richtig verstehe wird nach 'q' alle weitere Verarbeitung abgebrochen.
Wenn das so ist, hab ichs verstanden :idea:

Wesentlich besser als mein Sch... ist der Vorschlag von Joghurt
sed -e '/ccdcc/{s/d/f/;q;}'
geht so zwar nicht, aber Meillos Korrektur
sed -n '/ccdcc/{s/d/f/; p; q;}'
funktioniert richtig, habs jetzt so gemacht
sed -ne '/ccdcc/{s/d/f/p;q;}'

Vielen Dank für die umfassenden Informationen.
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Beitrag von Meillo » 14.01.2008 15:29:08

detix hat geschrieben:Also, wenn ich das richtig verstehe wird nach 'q' alle weitere Verarbeitung abgebrochen.
Wenn das so ist, hab ichs verstanden :idea:
ja.

Vielen Dank für die umfassenden Informationen.
Sehr gerne!
... denn irgendwie freue ich mich immer, wenn jemand ein Problem mit sed hat und ich dadurch mal wieder damit arbeiten darf. Sonst passiert das leider viel zu selten. :-)
Use ed once in a while!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 14.01.2008 16:06:02

Interessant, interessant.

Hätte dein Problem auch über zwei Schritte lösen müssen. Aber dass Ganze über eine sed-Anweisung ist natürlich schöner.

...muss ich mir merken. Und schon wieder was dazu gelernt :wink:
Oh, yeah!

Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Beitrag von detix » 15.01.2008 08:55:39

Eine Frage muß ich aber noch hinterherschieben...
Wie sieht es aus, wenn ich nur die 2te Fundstelle isolieren und bearbeiten will?
Wäre ja zu schön gewesen wenn das funktioniert:

x="aabaa\nbbcbb\nccdcca\nddedd\nccdccb\nccdccd"
echo -e $x | sed -ne '/ccdcc/{s/d/f/2p;q;}'

tuts aber leider nicht, '2p' bezieht sich auf die gesamte "Textdatei"
und nicht nur auf die Zeilen die den Suchbegriff enthalten,
wie muß ich es erweitern damit auch Das klappt?
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Beitrag von Meillo » 15.01.2008 11:37:01

detix hat geschrieben:Eine Frage muß ich aber noch hinterherschieben...
Wie sieht es aus, wenn ich nur die 2te Fundstelle isolieren und bearbeiten will?
Keine schöne Lösung, aber ich würde einfach beim ersten Durchlauf die Zeile mit dem ersten Vorkommen nicht ausgeben .... und dann im zweiten sed-Aufruf wie gewohnt agieren.

... das ist mir jedenfalls auf die Schnelle eingefallen. Ob es auch wirklich gute Lösungen mit sed gibt (geben kann) kann ich nicht sagen. Aber vielleicht soviel: sed bearbeitet (wie der Name schon sagt) Streams (Dateien zeilenweise). Variablen, die mitzählen wie viele Vorkommen des Suchbegriffs schon waren, sind nicht vorhanden .... dafür müsstest du dann AWK nehmen, das ist eine richtige Programmiersprache.

Was mir aber beim Schreiben noch einfällt: Wenn es eine Möglichkeit (Switch) gibt, die komplette Datei (und nicht zeilenweise) zu matchen, dann könntest du so etwas wie '/hallo.*hallo/' machen ...
Use ed once in a while!

Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Beitrag von detix » 19.01.2008 22:22:16

Mittlerweile habe ich die halbe bash_history mit sed Versuchen zugepflastert,
Ergebnis = Null. Mit echo und awk komme ich zu dieser Lösung,
um die 2., 3. oder sonstige Fundstelle zu isolieren und bearbeiten, hier die 2te:

Code: Alles auswählen

echo -e "aabaa\nbbcbb\nccdcca\nddedd\nccdccb\nccdccd" >_111
x=$(echo $(sed -ne /ccdcc/= _111) | awk '{print $2}')
sed -n "$x s/d/f/p" _111
Wen es interessiert, mit
sed -ne /ccdcc/= _111
werden nur die Zeilennummern der Fundstellen ausgegeben, leider in seperaten Zeilen.
Dies wird verhindert mit einem echo drumherum
echo $(sed -ne /ccdcc/= _111)
Nun kann der String nach awk weitergeleitet werden, der dann nur das 2te Wort,
(= die 2te Fundstelle) ausgibt
echo $(sed -ne /ccdcc/= _111) | awk '{print $2}'
und das Ganze wird in die Variable x geschrieben, mit
sed -ne "$x s/d/f/p" _111
wird dann nur in dieser Zeile (hier die 5te) gesucht, ersetzt und ausgegeben.
Vielleicht nicht die beste Lösung, aber auf jeden Fall eine die ich noch durchschaue.
Vielen Dank an Alle
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

Antworten