gudn tach!
Ich möchte jetzt nur alle Zeilen die zwischen ID 1 und ID 2 sind (inkl. die ID1 und ID2-Zeile) greppen. Ausserdem möchte ich dann ebenfalls die Start und Stopzeitzeile haben. Alles andere sollte raus.
also auch die zeilen, die von ID1 und IDX (X!=2) begrenzt werden.
eine moeglichkeit hat Rafael bereits genannt, also das zeilenweise abklappern wie es auch ein mensch tun wuerde.
da du in der ueberschrift was von "pattern" schriebst, moechte ich kurz noch eine regexp-moeglichkeit angeben. sie erfordert, dass die datei in einem string vorliegt.
als erstes wird der string bei den start-/stoppzeiten gesplittet:
my @arr = split(/^((?:Start|Stop)zeit .*)$/m, $str);
anschliessend wird jeder zeitblock seperat abgearbeitet
~~~perl
my $i;
for($i=@arr-2; $i>0; $i-=4){
$arr[$i]=~s/.*?(?=ID1\b|$)((?:ID1\b(?:(?!ID(?:[13-9]|2\d)).)*ID2\b)?)/$1/sg;
}
print join "\n", @arr;
nicht leicht zu verstehen ist der regulaere ausdruck
/.\*?(?=ID1\b|$)((?:ID1\b(?:(?!ID(?:[13-9]|2\d)).)\*ID2\b)?)/$1/sg;
ich werde ihn nicht komplett erklaeren, das wuerde vermutlich mehrere stunden dauern. also setze ich [grundwissen](http://perldoc.perl.org/perlre.html) voraus. falls du tatsaechlich den regulaeren ausdruck benutzen wirst, solltest du ihn genau verstanden haben, weil er einiges voraussetzt, von dem ich nicht weiss, ob es deine datei auch wirklich immer erfuellt.
.\*? matcht etwaige zu entfernende zeichen am anfang oder am ende des kompletten blockes oder zwischen gueltigen ID1...ID2-abschnitten; je nachdem an welcher stelle der regexp-cursor gerade ist; beachte den g-modifier.
.\*? matcht also z.b. auch einen ID1...ID3-abschnitt.
der term danach /(?=ID1\b|$)/ ist semantisch eigentlich ueberfluessig, es wuerde auch ohne ihn funzen. aber durch ihn wird der regulaere ausdruck beschleunigt, weil insg. weniger leere ersetzungen erfolgen, da der term .\*? damit nicht ganz so genuegsam frisst.
der grosse ausdruck
((?:ID1\b(?:(?!ID(?:[13-9]|2\d)).)\*ID2\b)?)
matcht alle gueltigen abschnitte, d.h. diejenigen, die von /ID1/ begonnen und von /ID2/ beendet werden, wobei dazwischen kein weiteres mal /ID\d/ stehen darf.
die aeusserste klammer dient nur dazu den kram dazwischen in $1 zwischenzuspeichern. $1 ist also leer, falls kein gueltiger abschnitt gefunden wird.
wenn die IDs nur einstellig sein duerften, koennten die wortenden \b wegfallen und der so entstehende term
((?:ID1(?:(?!ID[13-9]).)\*ID2)?)
waere besser verstaendlich.
zu dieser konstruktion
(?:(?!foo).)\*
vielleicht noch zwei saetze: es werden damit alle aufeinanderfolgenden zeichen gematcht, die nicht den string "foo" enthalten. auch wenn "foo" danach kaeme, wuerde von diesem term nicht mal das "f" gematcht.
was noch fehlt ist, dass die leeren bloecke eliminiert werden. aber das bekommst du wohl auch selbst hin. und ich ging davon aus, dass alle abschnitte (auch die zu loeschenden) immer mit ID1 eingeleitet werden.
prost
seth