Moin,
zuerst ein paar Bemerkungen zu Deinem Script:
Zitat von
jori
#!/bin/bash
DAT="*.dat" #charateristische Endung der Messdateien
for f in $DAT
do
cat $f | sed -e "sed-Magie1" <$f >tmp.$$
-e "sed-Magie2" <$f >>tmp$$ #um Ausgabe von Befehl2 an tmp.$$ anzuhängen(?)
-e "sed-Magie3" <$f >>tmp$$
-e "sed-Magie4" <$f >>tmp$$
mv tmp.$$ edit$f
done
- cat ist überflüssig, Du kannst sed den Dateinamen direkt als Argument übergeben.
- <$f ist doppelt gemoppelt, damit fütterst Du sed aus der Pipe und aus STDIN
- Die Ein- und Ausgabeumleitung zwischen den einzelnen -e-Optionen wird nicht funktionieren, das hängt man hinter die letzte Option bzw. das letzte Argument.
- Mehrere sed-Kommandos kann man mit Semikolon trennen, das ist übersichtlicher als viele -e-Optionen
So, und nun zum Thema: Ich habe mir erstmal Beispieldaten gebastelt:
Code:
jan@jack:~/tmp> for i in `seq 1 1000`; do echo -n "line $i" >>daten; test $i -eq 123 -o $i -eq 555 && echo -n " ;2.00 blablubb" >>daten; echo >>daten; done
jan@jack:~/tmp> sed 's/^/data2 /' daten >data2
So, und jetzt die Schleife + sed:
Code:
jan@jack:~/tmp> for dat in dat*; do
> sed -rn '1,8p;100p;250p;/;2\.00/H;${g;s/\n(.+)\n.*/\1/;p}' $dat >>edit.txt
> done
jan@jack:~/tmp> cat edit.txt
data2 line 1
data2 line 2
data2 line 3
data2 line 4
data2 line 5
data2 line 6
data2 line 7
data2 line 8
data2 line 100
data2 line 250
data2 line 123 ;2.00 blablubb
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 100
line 250
line 123 ;2.00 blablubb
Ist nur oberflächlich getestet.
Jan
EDIT: Mit ist noch eine Möglichkeit eingefallen, wie man die erste Zeile, die ";2.00" matcht, in der richtigen Reihenfolge ausgibt (das vorige Beispiel hat sie ja angehängt):
Code:
sed -rn '1,8p;100p;250p;/;2\.00/{x;/^$/{x;p};h}' daten
Das sollte ich vielleicht doch mal kurz kommentieren ;-)
Die ersten 3 Anweisungen ("1,8p;100p;250p;") sind wohl klar. Die nächste geschachtelte Anweisung ist die knifflige:
"/;2\.00/{...}" - Wenn die Zeile matcht, dann führe den Codeblock in den äußeren {} aus
"x;/^$/{x;p}" - tausche Inhalt von hold und pattern space aus (der Pattern space beinhaltet den Match, also hier die betreffende Zeile). Wenn jetzt der Pattern Space leer ist (beim ersten Treffer), dann tausche wieder Pattern und Hold Space (jetzt haben wir im Pattern Space wieder unsere Zeile) und gib sie aus.
"h" - Kopiere den Inhalt des Pattern Space (unsere Zeile) in den Hold Space; damit steht nach dem ersten Treffer im Hold Space diese Zeile und ist bei den nächsten Anfrage nicht mehr leer - voila!
Komisch - ich hatte doch noch was angehängt; wohl vergessen zu speichern - naja: Wenn eine Zeile, auf die das Pattern matcht, zufälligerweise eine der in den Zeilennummern aufgeführten ist, dann wird sie 2x ausgegeben. Das verhindert man, indem man die Reihenfolge der Anweisungen vertauscht (erst das PAttern, dann der Rest) und für das Pattern noch ein "d" (lösche den Pattern Space und mache mit der nächsten Zeile weiter) einfügt:
Code:
sed -rn '/;2\.00/{x;/^$/{x;p};h;d};1,8p;100p;250p' daten
Es lässt mich nicht los ;-) die letzte Version behandelt die Regel "nur die erste auf ;2.00 matchende Zeile ausgeben" mit höherer Priorität als die Regel "Zeilen 1..8, 100, 250 ausgeben". Wenn also eine 2. Zeile innerhalb der gewünschten Zeilennummern auch das Pattern enthält, dann wird sie nicht ausgegeben.
Wenn man es andersrum haben will, dann modifiziert man so:
Code:
sed -rn '/;2\.00/{x;/^$/{x;p;h;d};x;h};1,8p;100p;250p' daten
Ob das überhaupt auftreten kann, weiss ich nicht - vielleicht sind die Zeilen, die per Zeilennummer ausgegeben werden, ja irgendwelche Header oder Überschriften - eben nur für alle Fälle.
Nimmt das denn gar kein Ende? ;-) Es gibt ja noch eine Variante (da sieht man mal, was mangelnde Spezifikation ausrichtet): Gesetzt den Fall, dass die Zeilennummern höhere Priorität haben und eventuelle Matches gegen das Pattern bei ihnen überhaupt nicht berücksichtigt werden sollen:
Code:
sed -rn '1,8{p;d};100{p;d};250{p;d};/;2\.00/{x;/^$/{x;p};h}' daten
So, jetzt ist aber genug!
Lesezeichen