kostenloser Webspace werbefrei: lima-city


UNIX Problem

lima-cityForumProgrammiersprachenSonstige Programmiersprachen

  1. Autor dieses Themas

    buyworld

    buyworld hat kostenlosen Webspace.

    Hey,

    Ich hab eine Datei mit sequentiellen Daten (getrennt duch Leerzeilen)


    NachnameA
    VornameA
    AlterA

    NachnameB
    VornameB
    AlterB


    daraus soll mit Unix Mitteln (am liebsten awk) eine Datei gemacht werden:

    NachnameA VornameA AlterA
    NachnameB VornameB AlterB

    Wie kann ich das am besten lösen?

    LG
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Hallo :wave:

    Nicht getestet:

    tr -d '\n\r' < yourfile.txt
    xargs -n3 < file


    Alle Zeilenumbrüche entfernen und dann alle 3 Wörter einen Zeilenumbruch machen.

    https://stackoverflow.com/questions/3134791/how-do-i-remove-newlines-from-a-text-file
    https://stackoverflow.com/questions/15979802/how-to-insert-a-newline-n-after-x-numbers-of-words-with-awk-or-sed

    mfg :wave:

    Beitrag zuletzt geändert: 9.10.2014 14:32:53 von voloya
  4. Autor dieses Themas

    buyworld

    buyworld hat kostenlosen Webspace.

    Hey,

    danke für die schnelle Reaktion! Habe gerade einmal ausprobiert. Der Ansatz gefällt mir, allerdings habe ich nach dem 1. Schritt nur noch eine einzige Zeile:

    NachnameAVornameAAlterANachnameBVornameBAlterB


    Das ist dann quasi ein Wort und kann folglich nicht mehr getrennt werden. Hast du vielleicht eine Idee wie ich nach dem 1. Schritt Leerzeichen zwischen die 'Wörter' kriege? :D

    Trotzdem schonmal / nochmal danke

    LG
  5. thomasba

    Co-Admin Kostenloser Webspace von thomasba

    thomasba hat kostenlosen Webspace.

    Hallo,

    awk kann auch mit mehreren Zeilen umgehen. Auf dieser Seite gibt es dazu unter anderem ein Beispiel:
    https://www.gnu.org/software/gawk/manual/html_node/Multiple-Line.html

    Die Beispieldaten der Seite:
    Jane Doe
    123 Main Street
    Anywhere, SE 12345-6789
    
    John Smith
    456 Tree-lined Avenue
    Smallville, MW 98765-4321
    …


    Und das awk-Skript:
    # addrs.awk --- simple mailing list program
    
    # Records are separated by blank lines.
    # Each line is one field.
    BEGIN { RS = "" ; FS = "\n" }
    
    {
          print "Name is:", $1
          print "Address is:", $2
          print "City and State are:", $3
          print ""
    }


    Damit sollte das kein Problem sein.
  6. Hallo :wave:

    buyworld schrieb:
    allerdings habe ich nach dem 1. Schritt nur noch eine einzige Zeile:

    NachnameAVornameAAlterANachnameBVornameBAlterB


    Das ist dann quasi ein Wort und kann folglich nicht mehr getrennt werden. Hast du vielleicht eine Idee wie ich nach dem 1. Schritt Leerzeichen zwischen die 'Wörter' kriege? :DLG


    Ich wusste doch, dass ich etwas vergessen hatte. :wall:

    Vielleicht als ersten Schritt:

    sed -e 's/^/ /' dateialt.txt > dateineu.txt


    .. um ein Leerzeichen vor jede Zeile zu setzen.

    Habe momentan keinen Zugriff auf Linux, kann es also nicht ausprobieren.. Danach müssten dann die Leerzeichen am Zeilenanfang wieder entfernt werden. :biggrin:

    mfg :wave:
  7. Hi,

    das kannst du auch komplett mit sed machen, dann sähe das in etwa so aus;
    sed -e ':a;N;$!ba;s/\(.\)\n/\1 /g' file.txt > newFile.txt

    Zur Erklärung:
    sed ist ein Programm welches eine Datei Zeilenweise verarbeitet und dabei z.B. reguläre Ausdrücke zum suchen und ersetzten anwendet um die Ausgabe zu verändern. Die einzelnen Befehle werden durch Semikolon getrennt.

    :a
    erstellt ein label, in dem die aktuelle Zeile gespeichert wird.
    N
    sorgt dafür, dass die aktuelle Zeile und die nächste Zeile eingelesen wird. Dabei werden die Zeilen durch ein \n zusammen gesetzt.
    $!ba
    sorgt dafür, dass die statt der aktuellen Zeile mit dem label vom Anfang gearbeitet wird, hierbei muss beachtet werden, dass dadurch im laufe des Programms die komplette Datei im Arbeitspeicher landet und das Programm immer langsamer wird. Dieser Aufruf sollte also nicht bei zu großen Dateien angewendet werden. Ich würde aber sagen bis ca 1 oder 2 MB besteht kein Problem.
    s/\(.\)\n/\1 /g
    ist der reguläre Ausdruck der dafür sorgt, dass die Datei wie gewünscht formatiert wird. Er ersetzt den Zeilenumbruch hinter einem Wort durch ein Leerzeichen, aber nur wenn in der Zeile etwas steht.

    Auch in awk ist das Ganze nicht so wahnsinnig schwer, hier ist das Programm zwar länger, hat dafür aber nicht mehr die Probleme mit dem Speicher.
    awk 'function a(c){print substr(c,0,length(c))};BEGIN{b=""};{if($1==""){a(b);b=""}else{b=b$1" "}};END{a(b)}' file.txt > newFile.txt

    Ich habe das Programm hier einmal eingekürzt, schlauerweise speichert man es aber in einer Datei, z.B. reformatFile.awk und ruft das Programm dann so auf:
    awk -f reformatFile.awk file.txt

    In der Datei kann man das Programm dann auch besser strukturieren:
    function printTrimmed(outputLine){
        print substr(outputLine, 0, length(outputLine))
    }
    BEGIN{
        tmpOutputLine=""
    }
    {
        if($1==""){
            printTrimmed(tmpOutputLine)
            tmpOutputLine=""
        }else{
            tmpOutputLine=tmpOutputLine$1" "
        }
    }
    END{
        printTrimmed(tmpOutputLine)
    }


    Und zu guter Letzt möchte ich noch meinen persöhlichen Favoriten zeigen, nämlich perl. Perl ist eigentlich immer installiert, zumindest kenne ich keine Unix-Systeme mehr, die es nicht haben und es hat nicht die erwähnten Probleme, wie z.B. sed und ist andererseits sehr mächtig. Außerdem ist perl erheblich schneller als die anderen beiden Alternativen ;-) . Da sähe das Programm dem aus awk sehr ähnlich:
    perl -e '$a="";sub a{chomp $a;print $a."\n";$a=""}while(<>){chomp;$a.=$_." ";if($_ eq ""){a()}}a()' < file.txt > newFile.txt

    Oder um das Programm wieder übersichtlich darzustellen als file, welches so genutzt wird:
    perl reformatFile.pl < file.txt > newFile.txt
    und so aussähe:
    use strict;
    use warnings;
    my $tmpLine="";
    while(<>){
        chomp;
        $tmpLine.=$_." ";
        if($_ eq ""){
            printTrimmed();
        }
    }
    printTrimmed();
    sub printTrimmed {
        chomp $tmpLine;
        print $tmpLine . "\n";
        $tmpLine = "";
    }


    Wie du siehst gibt es da diverse Lösungen, die alle mit Unixboardmitteln zu erledigen sind.

    Ein kleiner Hinweis sei allerdings nocht gestattet, denn die Lösungen funktionieren, nicht alle gleich (außer die Perl-Variante). Die sed Variante funktioniert nur mit der GNU-Variante von sed, allerdings kann man das Problem beseitigen, indem man ähnlich wie in der awk-, oder perl-Variante das Programm in eine Datei schreibt. Ansonsten sollten die Programme aber alle laufen.

    Mit freundlichen Grüßen

    * Edit Hinweis zu GNU hinzugefügt

    Beitrag zuletzt geändert: 11.10.2014 15:33:07 von nemoinho
  8. thomasba

    Co-Admin Kostenloser Webspace von thomasba

    thomasba hat kostenlosen Webspace.

    nemoinho schrieb:
    Auch in awk ist das Ganze nicht so wahnsinnig schwer, hier ist das Programm zwar länger, hat dafür aber nicht mehr die Probleme mit dem Speicher.
    awk 'function a(c){print substr(c,0,length(c))};BEGIN{b=""};{if($1==""){a(b);b=""}else{b=b$1" "}};END{a(b)}' file.txt > newFile.txt

    Ich habe das Programm hier einmal eingekürzt, schlauerweise speichert man es aber in einer Datei, z.B. reformatFile.awk und ruft das Programm dann so auf:
    awk -f reformatFile.awk file.txt

    In der Datei kann man das Programm dann auch besser strukturieren:
    function printTrimmed(outputLine){
        print substr(outputLine, 0, length(outputLine))
    }
    BEGIN{
        tmpOutputLine=""
    }
    {
        if($1==""){
            printTrimmed(tmpOutputLine)
            tmpOutputLine=""
        }else{
            tmpOutputLine=tmpOutputLine$1" "
        }
    }
    END{
        printTrimmed(tmpOutputLine)
    }


    Mit dem von mir oben verlinkten Beispiel schenken sich perl und awk zeitlich gesehen nix :smile:
    Und es schaut auch noch besser aus ;-)
    Hier ist das ganze mit dem RS von awk auch nochmal erläutert:
    http://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/
  9. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!