Forum: PC-Programmierung Zeilenumbruch in Textdatei entfernen, wie am besten?


von Msp 4. (msp430_crew)


Lesenswert?

Hallo,
ich möchte am besten per Batch oder RegExp alle Umbrüche + 2 Leerzeichen 
nach 80 Zeichen löschen.

Beispiel:
1
m-description: Index attribute for DN whose values are NOT normalized in any
2
  way

Wie kann ich das am besten lösen?

Viele Grüße,
msp430_crew

von Klaus W. (mfgkw)


Lesenswert?

Mit awk lässt sich sowas bestimmt hinfummeln, wenn man vorher nicht an 
awk verzweifelt.

Abgesehen davon hat deine erste Beispielzeile keine 80 Zeichen.
Müssen es genau 80 sein, damit das LF entfernt wird?

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Mit awk lässt sich sowas bestimmt hinfummeln, wenn man vorher nicht an
> awk verzweifelt.

Geht garantiert.
Sowohl die Aufgabenstellung als auch das Verzweifeln :-)

Ich bevorzuge ganz ehrlich in solchen Fällen einen C-Compiler (zu meiner 
Schande). Noch ehe ich mir in AWK (oder SED) das was ich brauche 
zusammengesucht habe, läuft das C-Programm schon längst.

Kannst du mit einem Hammer umgehen, ist jedes Problem im Prinzip nur 
noch ein Nagel.

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ich bevorzuge ganz ehrlich in solchen Fällen einen C-Compiler (zu meiner
> Schande). Noch ehe ich mir in AWK (oder SED) das was ich brauche
> zusammengesucht habe, läuft das C-Programm schon längst.

Würde ich auch, aber den meisten Hilfesuchenden ist das eher
keine gute Empfelhung.
Wäre es für sie ein guter Weg, würden sie nicht fragen sondern
selbst drauf kommen.

Karl heinz Buchegger schrieb:
> Kannst du mit einem Hammer umgehen, ist jedes Problem im Prinzip nur
> noch ein Nagel.

Nun ist C ein recht vielseitiger Hammer, wozu also das schlechte
Gewissen? (Höchstens, weil man nicht C++ genommen hat.)

von Hrm (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Kannst du mit einem Hammer umgehen, ist jedes Problem im Prinzip nur
> noch ein Nagel.

Achso. Dann war das garnicht mein Daumen, sondern mein Problem das mir 
neulich so weh getan hat. <:-)

von Hc Z. (mizch)


Lesenswert?

1
awk --posix '/^.{80,}/ { printf $0; remove_spaces=1; next} remove_spaces==1 {sub(/^  /,""); print; remove_spaces = 0;} {print}'

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

1
ruby -e 'puts STDIN.read.gsub(/^(.{70,})\r?\n  /, "\\1 ")'

Ob ruby, perl oder awk, irgend ein Werkzeug zur Textverarbeitung sollte 
man schon haben, das mit C zu machen ist jedenfalls alles andere als 
effizient.

von Msp 4. (msp430_crew)


Lesenswert?

Vielen Dank für Eure Hilfe. Ich finde Ruby sehr interessant, würde mich 
gerne damit beschäftigen. Wie kann ich eine einlesen, verarbeiten und 
dann wieder zurückschreiben?
Mein Ansatz wäre folgender, der aber nicht funktioniert...ich 
überschreibe nur die ldif...:-(
1
datei=File.open("schema.ldif", "r")
2
text = datei.gets
3
datei.close
4
5
datei=File.open("schema.ldif","w")
6
datei.puts STDIN.read.gsub(/^(.{80,})\r?\n  /, "\\1 ")
7
datei.close

Danke schon mal :-)

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Naja, kein Wunder, du erstellst zwar eine Variable "text", aber 
verwendest sie nicht (und außerdem liest gets nur eine Zeile).

Probier's mal so:
1
text = File.read("schema.ldif") # (Abkürzung für open, read, close)
2
3
datei = File.open("schema.ldif", "w")
4
datei.write(text.gsub(/^(.{80,})\r?\n  /, "\\1 "))
5
datei.close

Oder Ruby-mäßiger ausgedrückt:
1
text = File.read("schema.ldif") # (Abkürzung für open, read, close)
2
3
File.open("schema.ldif", "w") do |datei|
4
  datei.write(text.gsub(/^(.{80,})\r?\n  /, "\\1 "))
5
end

(damit wir die Datei am Ende des Blocks automatisch geschlossen)

von Rolf Magnus (Gast)


Lesenswert?

> Karl heinz Buchegger schrieb:
>> Kannst du mit einem Hammer umgehen, ist jedes Problem im Prinzip nur
>> noch ein Nagel.
>
> Nun ist C ein recht vielseitiger Hammer, wozu also das schlechte
> Gewissen? (Höchstens, weil man nicht C++ genommen hat.)

Naja, Stringverarbeitung ist nicht gerade eine Stärke von C, um es mal 
vorsichtig auszudrücken, und Skriptsparachen wie awk (oder python, ruby, 
perl, php, ...) sind genau für sowas gemacht.
Und um mich auch an den Analogien zu beteiligen: Man bekommt auch mit 
einem Hammer eine Schraube in die Wand, aber mit einem Schraubenzieher 
geht's trotzdem besser.

von Msp 4. (msp430_crew)


Lesenswert?

Ich habe noch eine Verständnisfrage :-) :
1
 datei.write(text.gsub(/^(.{80,})\r?\n  /, "\\1 "))

Bedeutet so viel, dass ich den Inhalt von text einlese in einen String 
und bei jedem auftreten von \r?\n nach mindestens 80 Zeichen genau 
diesen Part austausche durch nichts? Was ist \\1? Steht das für den Part 
/..../ als 1 Variable?

VG

von Klaus W. (mfgkw)


Lesenswert?

für den Teil der Eingabe, der auf den ersten (und in diesem
Fall einzigen) mit () geklammerten Teilausdruck des Suchmusters
passt. Also die 80 Zeichen, die zu . passen.

\2 wäre entsprechend ein zweiter geklammerter Teilausdruck etc.

von Rolf Magnus (Gast)


Lesenswert?

Msp 430_crew schrieb:
> Ich habe noch eine Verständnisfrage :-) :
>
>  datei.write(text.gsub()
>
>
> Bedeutet so viel, dass ich den Inhalt von text einlese in einen String
> und bei jedem auftreten von \r?\n nach mindestens 80 Zeichen genau
> diesen Part austausche durch nichts?

Vom Ergebnis her ja, aber genau genommen bedeutet es, daß du diesen Part 
zusammen mit den 80 Zeichen davor ersetzt durch nur die 80 Zeichen 
davor.

von Ing. ET (Gast)


Lesenswert?

> Wäre es für sie ein guter Weg, würden sie nicht fragen sondern
> selbst drauf kommen.

Das stimmt bei mir nicht.
Ich bin oft von anderen, auch in diesem Forum, auf super Loesung 
gestossen worden, wo theoretisch von alleine draufkommen haette koennen.
Vielleicht geht es manch anderen auch so.

von Klaus W. (mfgkw)


Lesenswert?

Na gut, du hast es so gewollt:

KHB hat Recht (selten, aber schon wieder). Bevor man mühsam
einen regulären Ausdruck hinfummelt, der in einer Zeile viel
Unverständliches enthält und vielleicht das macht, was man will,
habe ich schneller ein C++-Programm mit vielleicht 10 Zeilen
geschrieben, das ich auch verstehe und bei Bedarf wesentlich
flexibler ist, wenn es doch komplizierter wird.

Je nach dem, wo man halt mehr Übung hat.

Die RE-Lösung ist nicht unbedingt schlechter, aber für mich
wäre sie fehlerträchtiger.

von Klaus W. (mfgkw)


Lesenswert?

na gut, etwas mehr als 10 Zeilen:
1
#include <iostream>
2
#include <fstream>
3
#include <string>
4
5
6
int main( int nargs, char **args )
7
{
8
  std::ifstream    datei( "t.txt" );
9
  std::ostream    &ausgabe = std::cout;
10
  // oder gleich in Datei: std::ofstream    ausgabe( "ausgabe.txt" );
11
  std::string      zeile;
12
  size_t           letzteZeilenlaenge = 0;
13
  size_t           zeilennummer       = 0;
14
15
  while( std::getline( datei, zeile ) )
16
  {
17
    if( ++zeilennummer==1 ) // erste Zeile immer ausgeben:
18
    {
19
      ausgabe << zeile;
20
    }
21
    else if( letzteZeilenlaenge>0
22
             &&
23
             zeile.size()>2
24
             &&
25
             zeile[0]==' '
26
             &&
27
             zeile[1]==' '
28
             )
29
    {
30
      // ab 2. Zeile Ausgabe mit einem Leerzeichen vorweg, aber kein
31
      // Zeilenvorschub, wenn es eine Folgezeile ist:
32
      ausgabe << zeile.substr( 1 );
33
    }
34
    else
35
    {
36
      // ansonsten vorhergehende Zeile mit LF beenden und die aktuelle
37
      // normal ausgeben:
38
      ausgabe << std::endl << zeile;
39
    }
40
41
    letzteZeilenlaenge = zeile.size();
42
  }
43
44
  ausgabe << std::endl; // letzte Zeile terminieren
45
}

von Klaus W. (mfgkw)


Lesenswert?

Wenn die Anfangszeile immer genau 80 Zeichen haben soll, um die
nächste anzuhängen, ist die Bedingung im else if... entsprechend
zu ändern.

(In deinem Beispiel sind es weniger als 80 Zeichen)

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Na gut, du hast es so gewollt:
>
> KHB hat Recht (selten, aber schon wieder).

Ui, da hab ich wieder was losgetreten :-)

Ich wollte doch eigentlich den TO dazu nötigen, mal ein Wort darüber zu 
verlieren, was er denn eigentlich von sich aus machen kann, bzw. ihm Mut 
machen, das Problem mit den Mitteln die er schon kennt anzugehen.


> habe ich schneller ein C++-Programm mit vielleicht 10 Zeilen
> geschrieben, das ich auch verstehe und bei Bedarf wesentlich
> flexibler ist, wenn es doch komplizierter wird.

Geht mir auch so.
(Ralf. Das C nicht zu ernst nehmen. Ob C oder C++ ist nicht so wichtig. 
In meiner C-Lernzeit hab ich gemerkt, dass


int main()
{
  int c;

  while( ( c == getchar() ) !== EOF ) {
    ...
  }
}

ein ziemlich flexibler Ansatz ist. Mit ein paar Modifikationen im ... 
Teil kann man damit recht schnell Textfilter bauen. Nach Bedarf diverse 
Zähler oder Flags dazu und man hat ziemlich flott etwas brauchbares. 
Natürlich nur, wenn man C schon kann.

Ich kann nun mal mit den Regular-Expression Sprachen nicht viel anfangen 
und für mich führt das schneller zu einer brauchbaren Lösung.

Aber ich geb zu, ich hab die Aufgabenstellung nicht wirklich verstanden. 
Wie, was, 80 Zeichen, Umbrüche?

Was soll das Ziel sein?
Eine Textzeile, die auf irgendwelchen dubiosen Wegen auf mehrere 
aufgeteilt wurde, wieder zu einer einzigen zu vereinen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.