Mike: Dateiarbeit

Hallo,

ich hab so als Anfänger meine Probleme mit Perl.

Ich weiss wie man eine Datei öffnen kann und sich den Inhalt angucken kann.

Aber wie kann ich eine Datei öffnen, Zeile für Zeile die letzen 2 Zeichen entfernen und die Datei wieder schließen (so das jetzt in jeder Zeile die letzen beiden Zeichen weg sind)?

Zeichen entfernen kann man ja mit chop(). aber irgendwie kommen ich zu keinem vernünftigen Script...

#!/usr/bin/perl -w

Liest Datei ein und entfernt Zeichen am Zeilenende/

print "Dateiname:  ";
$name = <STDIN>;

open(HANDLE, ">>" .  $name) || die "ERROR beim OEFFNEN\n";
while (<HANDLE>)
{
chop ($_);
chop ($_);
print $_;
}
close(HANDLE);

Kann mir hier jemand weiterhelfen?

MFG Mike

  1. Ich weiss wie man eine Datei öffnen kann und sich den Inhalt angucken kann.

    Aber wie kann ich eine Datei öffnen, Zeile für Zeile die letzen 2 Zeichen entfernen und die Datei wieder schließen (so das jetzt in jeder Zeile die letzen beiden Zeichen weg sind)?

    Du kannst zwar eine Datei zum lesen und schreiben öffnen, das wäre aber in deinem Falle extrem umständlich, da du dann mit Filezeigern arbeiten musst (seek) und schnell Problem bekommst.

    Das einzige sinnvolle wäre eine zweite temporäre Datei zum schreiben zu öffnen und dort den veränderten Inhalt reinschreiben. die Orginaldatei löschen und die temporäre Datei umbennen.

    Liest Datei ein und entfernt Zeichen am Zeilenende/

    print "Dateiname:  ";
    $name = <STDIN>;

    Du solltest immer mit use strict arbeiten um z.b. Tippfehler zu finden/vermeiden.

    open(HANDLE, ">>" .  $name) || die "ERROR beim OEFFNEN\n";

    Hier kannst du noch den Grund mit ausgeben

    open(HANDLE, ">>" .  $name) || die "ERROR beim OEFFNEN ($!)\n";

    while (<HANDLE>)
    {
    chop ($_);
    chop ($_);
    print $_;

    Dir ist aber klar, dass deine neue Datei dann keine Zeilen mehr hat, da du ja auch "\n" damit entfernst?

    Struppi.

    1. Hm, so richtit weiss ich nicht wie du das meinst mit der temp. Datei.

      Das "\n" könnt ich ja wieder anhänen mit

      print $_ . "\n";

      oder?

      1. Hallo Mike

        Hm, so richtit weiss ich nicht wie du das meinst mit der temp. Datei.

        Eine Datei die du nachher wieder löscht.

        Das "\n" könnt ich ja wieder anhänen mit

        print $_ . "\n";

        oder?

        Sicher, solltest du evtl. auch tun.

        Struppi.

        1. Hab das Script jetzt nochmal bearbeitet.
          Wäre das so in Ordnung?

          #!/usr/bin/perl -w

          Liest Datei ein und entfernt Zeichen am Zeilenende/

          print "Dateiname:  ";
          $name = <STDIN>;

          print "Name Ausgabedatei: ";
          $ausgabe = <STDIN>;

          open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
          open(HANDLE, ">" . &ausgabe);
          while (<HANDLE>)
          {
          chop ($_);
          chop ($_);
          print $_ . "\n";
          }
          close(HANDLE);

          1. geht natürlich nicht
            -&ausgabe + $ausgabe

            leider steht in der ausgabe-datei ix drinn, aber warum?

          2. Hab das Script jetzt nochmal bearbeitet.
            Wäre das so in Ordnung?

            nö.

            #!/usr/bin/perl -w

            Liest Datei ein und entfernt Zeichen am Zeilenende/

            print "Dateiname:  ";
            $name = <STDIN>;

            Nach wie vor, du solltest wirklich mit use strict Arbeiten, das wird dir vieles erleichtern.

            print "Name Ausgabedatei: ";
            $ausgabe = <STDIN>;

            eine temporäre Datei zeichnet sich dadurch aus, dass sie nach beendigung des Skriptes wieder gelöscht werden kann, es ist also nicht nötig den Dateiname zu abzufragen.

            Falls du dier Orignaldatei noch behalten willst kannst du auch einfach eine Kopie anlegen.

            z.b.
            my $name = <STDIN>;
            my $orginal = "$name.kopie";

            ren $name, $orginal;

            open IN, $orginal || die "ERROR beim OEFFNEN ($!) \n";
            open OUT, ">$name";

            open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
            open(HANDLE, ">" . &ausgabe);

            Wenn du beiden den gleichen Handle gibst wird das ncihts.

            while (<HANDLE>)
            {
            chop ($_);
            chop ($_);
            print $_ . "\n";

            Du musst die Ausgabe auch in irgendeine Datei printen.

            Struppi.

            1. Hm use strict kenne ich nicht, steht in meinem Perl-Buch gar net drinn.

              #!/usr/bin/perl -w

              Liest Datei ein und entfernt Zeichen am Zeilenende/

              print "Dateiname:  ";
              $name = <STDIN>;

              print "Name Ausgabedatei: ";
              $ausgabe = <STDIN>;

              open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
              while (<HANDLE>)
              {
              chop ($_);
              chop ($_);
              $temp = $_;

              open(file, ">>" . $ausgabe);
                print $temp . "\n";
              close(file);
              }
              close(HANDLE);

              so gehts aber auch nicht, obwohl dem print doch jetzt mitgeteilt wird das es in $ausgabe schreiben soll. Oh man, Perl ist doch ganz schön schwehr.

              1. Tag Mike.

                open(file, ">>" . $ausgabe);
                  print $temp . "\n";
                close(file);
                so gehts aber auch nicht, obwohl dem print doch jetzt mitgeteilt wird das es in $ausgabe schreiben soll.

                Nein, wo? Wenn du print $string aufrufst, dann schreibt Perl $string nach STDOUT. Du musst schon einen Datei-Handler angeben (file ist m.E. nicht wirklich glücklich gewählt), siehe Funktion print().

                Siechfred

                1. Danke, ich habs, ist zwar nicht sehr proffesionell, aber für meine Zwecke funnktionierts :-)

                  #!/usr/bin/perl -w

                  Liest Datei ein und entfernt Zeichen am Zeilenende/

                  print "Dateiname:  ";
                  $name = <STDIN>;

                  print "Name Ausgabedatei: ";
                  $ausgabe = <STDIN>;

                  open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
                  while (<HANDLE>)
                  {
                  chop ($_);
                  chop ($_);
                  $temp = $_;

                  open(DATEI, ">>" . $ausgabe);
                    print DATEI $temp . "\n";
                  close(DATEI);
                  }
                  close(HANDLE);

                  Danke für die Hilfe, war bestimmt ein anstrengender Zeitgenosse.

                  MFG Mike

                  1. #!/usr/bin/perl -w

                    Liest Datei ein und entfernt Zeichen am Zeilenende/

                    use strict;

                    print "Dateiname:  ";
                    $name = <STDIN>;

                    my $name = <STDIN>;

                    print "Name Ausgabedatei: ";
                    $ausgabe = <STDIN>;

                    Wie gesagt halte ich für überflüssig, du kannst doch ohne Problem zur Laufzeit einen Dateinamen aus dem Orginal erstellen.

                    z.n.
                    my $ausgabe = "$name.kopie";

                    open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
                    while (<HANDLE>)
                    {
                    chop ($_);
                    chop ($_);
                    $temp = $_;

                    open(DATEI, ">>" . $ausgabe);
                      print DATEI $temp . "\n";
                    close(DATEI);

                    Das ist umständlich , warum öffnest und schliesst du doe Datei ständig?

                    open(HANDLE, "<" . $name) || die "ERROR beim OEFFNEN ($!) \n";
                    open(DATEI, ">>" . $ausgabe);
                    while (<HANDLE>)
                    {
                    chop ($_); chop ($_);
                    print DATEI "$_\n";
                    }
                    close(DATEI);

                    close(HANDLE);

                    Struppi.

                    1. Moin.

                      Und den/die Filenamen kannst Du Dir auch von der Kommandozeile holen:

                      my $name = $ARGV[0];
                      my $ausgabe = $ARGV[1];

                      Gruß Frank

              2. Hm use strict kenne ich nicht, steht in meinem Perl-Buch gar net drinn.

                Dann sind die alt oder schlecht.

                so gehts aber auch nicht, obwohl dem print doch jetzt mitgeteilt wird das es in $ausgabe schreiben soll. Oh man, Perl ist doch ganz schön schwehr.

                Du musst die Datei öffnen und in den HANDLE schreiben, wie übrigens in den meisten anderen Programmiersprachen auch, das hat nix mit Perl zu tun.

                Struppi.

  2. Tag Mike.

    Aber wie kann ich eine Datei öffnen, Zeile für Zeile die letzen 2 Zeichen entfernen und die Datei wieder schließen (so das jetzt in jeder Zeile die letzen beiden Zeichen weg sind)?

    Behandle die Zeile einfach mit chomp(), die letzten zwei Zeichen kannst du mit Hilfe von substr() kombiniert mit length() "abschneiden". Den gekürzten String schreibst du dann wieder in die Datei, aber vergiss den Zeilenumbruch am Ende nicht. Sicher ginge es auch anders, aber dazu sind die Informationen nicht ausreichend.

    Siechfred

    1. Hallo Siechfred!

      Eigentlich hab ich ja folg. Prob:

      Habe XML-Daten aus Windows, mit denen ich unter Unix weiterarbeiten will. Nur unter Unix steht jetzt in den XML-Dateien am Ende jeder Zeile ein ^M, und da dachte ich mir ich schreibe ein Perl-Script, mit dem ich das ^M wieder entferne. Das das so kompliziert werden wird hätt ich allerdings nicht gedacht.

      1. Tag Mike.

        Habe XML-Daten aus Windows, mit denen ich unter Unix weiterarbeiten will. Nur unter Unix steht jetzt in den XML-Dateien am Ende jeder Zeile ein ^M, und da dachte ich mir ich schreibe ein Perl-Script, mit dem ich das ^M wieder entferne. Das das so kompliziert werden wird hätt ich allerdings nicht gedacht.

        Aha, da kommen wir der Sache näher. Grund des Ganzen ist die Windows-Eigenart, einen Zeilenumbruch als "CR-LF" (oder "\015-\012") zu notieren, unter Unix allerdings nur das "LF" verwendet wird. Das ominöse "CR" wird nicht erkannt und ASCII-gerecht als ^M dargestellt. Du solltest also besser an der Ursache ansetzen. Vielleicht hilft dir ja das Programm CorrecText weiter.

        Siechfred

        1. Genau das ist mein Problem. Nur kommt es noch schlimmer.

          Die XML-Dateien wurden nicht von mir nach Unix verschoben und existieren nicht mehr unter Widows. Deswegen muß ich das ^M jetzt auch irgendwie unter Unix wieder loswerden.

          1. Tag Mike.

            Die XML-Dateien wurden nicht von mir nach Unix verschoben und existieren nicht mehr unter Windows. Deswegen muß ich das ^M jetzt auch irgendwie unter Unix wieder loswerden.

            Hilft dir vielleicht dos2unix?

            Siechfred

            1. geht leider nicht. hat keinen Zugriff auf /dev/kbd.
              gibt es nicht irgend ein unix kommando mit dem man das bewerkstelligen kann?

              1. Hallo,

                geht leider nicht. hat keinen Zugriff auf /dev/kbd.
                gibt es nicht irgend ein unix kommando mit dem man das bewerkstelligen kann?

                versuch mal:

                recode ibmpc..lat1 [dateiname]

                oder
                iconv -f CP850 -t ISO-8859-1 [dateiname] > [ausgabe]

                Backups nicht vergessen.

                Liebe Gruesse,
                Gero

              2. geht leider nicht. hat keinen Zugriff auf /dev/kbd.
                gibt es nicht irgend ein unix kommando mit dem man das bewerkstelligen kann?

                perl -pi.bak -e 's!\015\012!\012!g' file.txt

      2. Moin.

        Habe XML-Daten aus Windows, mit denen ich unter Unix weiterarbeiten will.

        Wie kommen Deine Dateien von Windows nach UNIX? Transferiere sie einfach mit ftp und wähle als Transfermode ASCII, dann stimmt es. Dein FTP-Client auf der UNIX-Seite weiß ja, daß als Zeilenende nur 0x0a gilt und speichert automatisch im richtigen Mode.

        Das das so kompliziert werden wird hätt ich allerdings nicht gedacht.

        Naja, isses ja auch nicht. So zum Beispiel gehts:

        open(HANDLE,"+<$name") || die $!;
        #Datei sichern gegen gleichzeitges Schreiben durch andere
        flock(HANDLE,2);
        binmode (HANDLE);
        #Inhalt lesen
        @inhalt = <HANDLE>;
        #Dateizeiger auf den Anfang
        seek (HANDLE, 0, 0);
        #Alles danach abschneiden
        truncate (HANDLE, 0);
        foreach (@inhalt){
        chop $_;
        chop $_;
        #und wieder 'reinschreiben
        print HANDLE $_ ."\x0a";
        }
        close HANDLE;

        Gruß Frank

        1. Moin.

          'n Nachtrag: schon mal probiert: "dos2unix"? Ist vielleicht bei Deiner UNIX-Distribution dabei, SunOS 5.8 hats z.B., steht unter /bin

          Gruß Frank

        2. Moin.

          Sicherer ist diese Variante, da sie nur 0x0d gegen nix austauscht. Damit bleiben Files die bereit im UNIX-Format vorliegen, unverändert. Außerdem: in @ARGV steht das, was Du dem Script übergibts: der Filename, Aufruf: script.pl <dateiname>

          Das sollte nun genau das tun, was Du willst...

          #!/bin/perl
          open(HANDLE,"+<@ARGV") || die $!;
          binmode (HANDLE);
          flock(HANDLE,2);
          @inhalt = <HANDLE>;
          seek (HANDLE, 0, 0);
          truncate (HANDLE, 0);
          $temp = join("",@inhalt);
          $temp =~ s/\r//g;
          print HANDLE $temp;
          close HANDLE;

          Schönes Wochenende,
          Gruß Frank

          1. Das sollte nun genau das tun, was Du willst...

            #!/bin/perl

            Ohne Warnungen und use strict;?

            Ich weiß das es Cracks gibt, bei denen das verpönt ist, aber gerade Anfängern sollte man sowas nicht beibringen, da die Fehlersuche so enorm erschwert wird.

            open(HANDLE,"+<@ARGV") || die $!;
            binmode (HANDLE);
            flock(HANDLE,2);
            @inhalt = <HANDLE>;
            seek (HANDLE, 0, 0);
            truncate (HANDLE, 0);
            $temp = join("",@inhalt);
            $temp =~ s/\r//g;
            print HANDLE $temp;
            close HANDLE;

            Aber Achtung!

            Die Orginal Daten sind danach nicht mehr da, ich würde Sicherhietshalber eine Kopie anlegen. Auißerdem kann bei besonders grossen Dateien das komplette einlesen u.U. Speicherplatzproblem ergeben.

            Struppi.

            1. Moin.

              Ohne Warnungen und use strict;?
              Ich weiß das es Cracks gibt, bei denen das verpönt ist, aber gerade Anfängern sollte man sowas nicht beibringen, da die Fehlersuche so enorm erschwert wird.

              Du hast recht, also so:

              #!/bin/perl
              use strict;
              my @inhalt;
              my $temp;

              Die Orginal Daten sind danach nicht mehr da, ich würde Sicherhietshalber eine Kopie anlegen.

              Das muß Mike überlegen, ob er die Orignale noch retten will.

              Auißerdem kann bei besonders grossen Dateien das komplette einlesen u.U. Speicherplatzproblem ergeben.

              Auch wahr. Und in diesen Fall hilft dann wohl nur das Arbeiten mit einem temporären File. Wobei das mit dem Original dann auch gekärt ist.

              Gruß Frank

              1. Ohne Warnungen und use strict;?
                Ich weiß das es Cracks gibt, bei denen das verpönt ist, aber gerade Anfängern sollte man sowas nicht beibringen, da die Fehlersuche so enorm erschwert wird.

                Du hast recht, also so:

                #!/bin/perl

                #!/bin/perl -w

                Die Orginal Daten sind danach nicht mehr da, ich würde Sicherhietshalber eine Kopie anlegen.

                Das muß Mike überlegen, ob er die Orignale noch retten will.

                Vermutlich hat er eh ein Backup davon, bei seinen Versuchen hat er mit Sicherheit die Datei schon mehrmals komplett gelöscht

                Auißerdem kann bei besonders grossen Dateien das komplette einlesen u.U. Speicherplatzproblem ergeben.

                Auch wahr. Und in diesen Fall hilft dann wohl nur das Arbeiten mit einem temporären File. Wobei das mit dem Original dann auch gekärt ist.

                Wobei dies bei Textdateien eher unwahrscheinlich ist (ausser es sind log-Files o.ä.)

                Jetzt aber Wochenende ;-)

                Struppi.

                1. Moin.

                  Jetzt aber Wochenende ;-)

                  Nee, erst noch'n Kaffee (der Compiler läuft soooo lange), aber dann!

                  Schönes Wochenende,
                  Gruß Frank