• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

Text-Dateien mit Regulären Ausdrücken verarbeiten

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Hi,

weiß jemand wie ich am besten automatisiert Text-Dateien mit regulären Ausdrücken bearbeiten kann? Das Problem ist allerdings, dass ich z.B. mehrere Zeilen zu einer zusammenfassen möchte. Somit scheitern die Ruby-Einzeiler, welche ich im Netz gefunden habe, da Sie scheinbar zeilenweise vorgehen.

Auch brauche also irgendwas, was bei OS X dabei ist und z.B. über AppleScript aufgerufen werden kann. (do shell ist ok).

Ich habe noch SED gefunden, doch das hat irgendwie eine komische Syntax und scheint auch nicht mehrere Zeilen gleichzeitig (mulit-line) zu verarbeiten, oder?
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Danke, funktioniert leider auch nicht.

Ich habe z.B. folgende Datei:
Code:
zeile1
;
zeile2;

daraus soll werden:
Code:
zeile1\n;
zeile2;

Folgendes funktioniert leider nicht:
Code:
perl -i -pe 's/[\n\r];/\\n;/s' datei.txt

In Textmate oder im Regex Widget funktioniert das aber.
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Klar, weil Du perl mit -p angewiesen hast, zeilenweise zu arbeiten. Versuch mal:

Code:
perl -i -e 'SLURP: { local $/; $_=<> } s/[\n\r]+;/\\n;/gs; print' datei.txt

Setzt natürlich voraus, daß Dein Text auf einen Rutsch in den Speicher paßt.
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Ah danke, funktioniert, auch wenn ich's nicht ganz verstehe. Geht's nicht einfacher? Bzw. gibt's keine Alternative zu Perl? Bei OS X ist ja eine Menge dabei. SED, AWK, Python, Ruby, PHP etc. ich habe aber nicht so viel Erfahrung um zu entscheiden, was nun geeignet ist. Mit SED habe ich schon experimentiert, aber da kriege ich auch keine Multi-Line hin. Das mit Perl reicht natürlich erstmal, ich hätte aber gerne was, was ich mir besser merken kann, da ich sowas immer wieder mal brauche.
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Setzt natürlich voraus, daß Dein Text auf einen Rutsch in den Speicher paßt.

Meine Datei ist 300 KB groß, scheinbar passt das nicht. Super, also auch keine Lösung. Ich könnte auch einen Texteditor per AppleScript steuern, doch leider ist nicht auf jedem Rechner der gleiche installiert.
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Unix hält ja noch einiges anderes bereit. Wären YACC, Bison, Flex etc. geeignet? Gibt's noch was anderes?
 

mullzk

Linsenhofener Sämling
Registriert
04.01.04
Beiträge
2.529
awk/sed, das einzig wahre für masochisten :)
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
sehr hilfreiche aussage ... bist du masiochist genug, um mir zusagen, ob eines der beiden mehrzeilige reguläre Ausdrücke beherrscht? ;)
 

mullzk

Linsenhofener Sämling
Registriert
04.01.04
Beiträge
2.529
ok, geb ich zu, war nicht sehr hilfreich, vor allem weil sie tatsächlich vor allem falsch gewesen zu sein schien - sed kommt da anscheinend auch nicht klar (auch wenn die chance wesentlich grösser ist, dass ich irgendwo einen denkfehler eingebaut habe, als dass sed/awk irgend etwas nicht kann...). sorry.

damit ich doch noch etwas halbwegs produktives geschrieben habe: kehr doch die verarbeitungsart einfach um:

perl -i -pe 's/[^;][\n\r]/\\n/s' datei.txt
perl -i -pe 's/\\n[^;]/\n/s' datei.txt

(1. zeile: allen zeilen, die nicht mit ; abgeschlossen werden, wird ein \n hinzugefügt und die newline weggenommen. 2. zeile: korrektur: wo ein \n hinzugefügt wurde, die nächste zeile aber nicht mit einem ; beginnt, nehmen wir es wieder auseinander.)
oder so irgendwie...
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
nur 300k und dann passt es nicht auf einmal in den Speicher!?

Versuch's so:
Code:
perl -i.bak -pe 's/[\015\012]+// unless eof;s/^([^;])/\n$1/ if $.>1;' text.txt
Das ist im Prinzip die Idee von mullzk.
1. Entferne jedes Zeilenende außer am Ende der Datei
2. hänge ein Zeilenende vor eine Zeile, wenn sie nicht mit ; beginnt und nicht die erste ist
Ist ungetestet, sollte aber klappen.

Ich verwende immer \012 und \015 statt \n und \r, da letztere vom Betriebsystem abhängig sind.

Nebenbei: Lieber als sed und/oder awk zu lernen, würde ich mich gleich mit perl beschäftigen. Es ist mächtiger als die beiden.
 

Geigaman

Macoun
Registriert
17.03.06
Beiträge
116
Ein Vorschlag wäre eine PHP Datei zu schreiben, dann hättest du auch gleich noch eine GUI dabei. (Ok, die GUI macht alles ein bisschen aufwändiger.) Allerdings hättest du dann die Arbeit nur einmal. PHP ist auch ziemlich portabel, zumindest was Mac OS X betrifft (Websharing). Für andere Betriebssysteme gäbs dann Ansätze wie XAMPP o.ä. Ein weiterer Vorteil ist, dass die RegExp in PHP fast deckungsgleich mit denen in Perl sind, du also nicht 2 verschiedene Sachen lernen musst.
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Danke für die Vorschläge. Mit PHP wäre mir natürlich lieber, da ich das besser kenne. Ich dachte aber eher an Automatismen ohne GUI, welche ich per Applescript aus Filemaker aufrufen kann. Da wären Einzeiler sehr praktisch, da man dann keine Programmdateien auf den Rechnern ablegen muss. Da ich eigentlich immer mit regulären Ausdrücken zum Ziel komme, dachte ich, es gäbe da eine einfache Lösung. Eine coole Alternative wären ja z.B. RegEx-Droplets, also kleine Progrämmchen wo man Dateien draufzieht.
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Eine coole Alternative wären ja z.B. RegEx-Droplets, also kleine Progrämmchen wo man Dateien draufzieht.
Biite sehr.
Bitte gleich.
on open some_things
   repeat with something in some_things
      set information to info for something
      if folder of information is false then
         treat(something)
      end if
   end repeat
end open

on treat(a_file)
   try
      do shell script "perl -i.bak -pe '
         s/[\\015\\012]+// unless eof;
         s/^([^;])/\\n$1/ if $.>1;
      ' " & quoted form of POSIX path of a_file
   end try
end treat
 

Tekl

Fairs Vortrefflicher
Registriert
01.06.05
Beiträge
4.630
Oi, Goil! Megafetten Dank! Allerdings ist das noch keine richtige Lösung für mein Problem mit den mehrzeiligen Regex, so was brauche ich nämlich häufiger in deutlich komplexerer Form. Ich wollte hier nur ein recht einfaches Beispiel geben zur Veranschaulichung geben.
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Allerdings ist das noch keine richtige Lösung für mein Problem mit den mehrzeiligen Regex, so was brauche ich nämlich häufiger in deutlich komplexerer Form.
In Perl gibt es noch sowas wie:
Code:
while (<>) {
  if (/anfang/ .. /ende/) {
    # verarbeite etwas, das von "anfang" und "ende" begrezt ist
  }
}
Das hängt aber alles vom speziellen Problem ab. Deswegen mein Vorschlag: Nimm Perl!