none
Daten in Textdatei mit PowerShell sortieren RRS feed

  • Frage

  • Hallo Leute,

    meine Frage ist, wie man verschiedene Zeilen, wie z.B.

    GH ................. 24.07.2016
    HD ................. 12.09.2016
    JD ................. 15.09.2016
    KL ................. 15.09.2016
    UZ ................. 13.09.2016
    TO ................. 11.08.2016

    wobei anstelle der Punkte Texte stehen, nach Datum sortieren kann. Ist dies überhaupt möglich ?

    Vielen Dank an alle die mir helfen.

    MfG

    Szabi_123



    Donnerstag, 15. September 2016 07:57

Antworten

  • $datei = 'GH ................. 24.07.2016',
    'HD ................. 12.09.2016',
    'JD ................. 15.09.2016',
    'KL ................. 15.09.2016',
    'UZ ................. 13.09.2016',
    'TO ................. 11.08.2016'
    
    $daten = foreach ($zeile in $datei){
        
        $text = $zeile.Substring(0,$zeile.Length-10)
        $datum = $zeile.Substring($zeile.Length-10,10) | Get-Date
        
        $co = New-Object -TypeName System.Object
        $co | Add-Member -MemberType NoteProperty -Name Text -Value $text
        $co | Add-Member -MemberType NoteProperty -Name Datum -Value $datum
        $co
    }
    $daten | Sort-Object -Property Datum

    $datei kannst du natürlich auch mit Get-Content füllen.

    Das ganze funktioniert natürlich nur, wenn die letzten 10 Zeichen in jeder Zeile das Datum im Format TT.MM.YYYY haben


    Donnerstag, 15. September 2016 08:20
  • Wenn das Datum an beliebiger Stelle steht, kann man es über einen Regulären Ausdruck suchen:
    $datei = 'GH ................. 24.07.2016',
    'HD ................. 12.09.2016',
    'JD ................. 15.09.2016',
    'KL ................. 15.09.2016',
    'UZ ................. 13.09.2016',
    'TO ................. 11.08.2016'
    
    $daten = @()
    
    foreach ($zeile in $datei)
    {
        $datum =  [Regex]::Match($zeile,"\d{2}\.\d{2}\.\d{4}").Value | Get-Date
        
        $co = New-Object -TypeName System.Object
        $co | Add-Member -MemberType NoteProperty -Name Text -Value $Zeile
        $co | Add-Member -MemberType NoteProperty -Name Datum -Value $datum
        $Daten += $co
    }
    $daten | Sort-Object -Property Datum

    Donnerstag, 15. September 2016 08:40
  • Hallo,

    wie hpotsirhc | Christoph schon angedeutet hat, ist das eher etwas für ein Script, welches man am besten in der Powershell_ise entwickelt. Das macht die Entwicklung viel einfacher.

    Mit der Annahme, dass Deine Daten in einer Datei mit dem Namen 'Datei.txt' stehen, sollte der Code dann ungefähr so aussehen:
    (den Pfad musst Du noch ergänzen!)

    $Inhalt = Get-Content -Path "<Pfad zur Textdatei>\Datei.txt"
    $SortierbarerInhalt = Foreach($Zeile in $Inhalt){
        $Zeile -match "(.+)((\d{2}\.){2}\d{4})" | Out-Null
        [PSCustomObject]@{
    	    Text = $Matches[1]
    	    Datum = Get-Date -Date $Matches[2]
        }
    }
    $SortierbarerInhalt | Sort-Object -Property Datum


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''



    Donnerstag, 15. September 2016 11:34

Alle Antworten

  • $datei = 'GH ................. 24.07.2016',
    'HD ................. 12.09.2016',
    'JD ................. 15.09.2016',
    'KL ................. 15.09.2016',
    'UZ ................. 13.09.2016',
    'TO ................. 11.08.2016'
    
    $daten = foreach ($zeile in $datei){
        
        $text = $zeile.Substring(0,$zeile.Length-10)
        $datum = $zeile.Substring($zeile.Length-10,10) | Get-Date
        
        $co = New-Object -TypeName System.Object
        $co | Add-Member -MemberType NoteProperty -Name Text -Value $text
        $co | Add-Member -MemberType NoteProperty -Name Datum -Value $datum
        $co
    }
    $daten | Sort-Object -Property Datum

    $datei kannst du natürlich auch mit Get-Content füllen.

    Das ganze funktioniert natürlich nur, wenn die letzten 10 Zeichen in jeder Zeile das Datum im Format TT.MM.YYYY haben


    Donnerstag, 15. September 2016 08:20
  • Wenn das Datum an beliebiger Stelle steht, kann man es über einen Regulären Ausdruck suchen:
    $datei = 'GH ................. 24.07.2016',
    'HD ................. 12.09.2016',
    'JD ................. 15.09.2016',
    'KL ................. 15.09.2016',
    'UZ ................. 13.09.2016',
    'TO ................. 11.08.2016'
    
    $daten = @()
    
    foreach ($zeile in $datei)
    {
        $datum =  [Regex]::Match($zeile,"\d{2}\.\d{2}\.\d{4}").Value | Get-Date
        
        $co = New-Object -TypeName System.Object
        $co | Add-Member -MemberType NoteProperty -Name Text -Value $Zeile
        $co | Add-Member -MemberType NoteProperty -Name Datum -Value $datum
        $Daten += $co
    }
    $daten | Sort-Object -Property Datum

    Donnerstag, 15. September 2016 08:40
  • Danke erstmal :-)

    Mein jetziges Problem besteht grade darin, dass in meiner PowerShell dieses Zeichen ">>" angezeigt wird.

    Muss ich noch was bestimmtes machen, damit mir die sortierten Zeilen angezeigt werden? Zum Schluss noch die Frage, ob die Daten nur in der PowerShell sortiert werden, oder in dem Textdokument.

    Vielen Dank schonmal

    Donnerstag, 15. September 2016 08:48
  • ">>" deutet darauf hin, dass der Debugger aktiv ist. Eigentlich sollen die Zeilen direkt eingegeben werden.

    Nein, natürlich ist die Änderung nicht im Textdokument. Das Dokument liegt auf der Festplatte, deine Variablen liegen im Hauptspeicher. Zum Ändern musst du das Dokument überschreiben (Set-Content).

    Donnerstag, 15. September 2016 09:11
  • Mhm komisch.

    Sobald ich foraech(....) { eingebe kommt >>.

    Mache ich da was falsch ?

    Donnerstag, 15. September 2016 09:17
  • Du gibst das aber schon in die Powershell ISE und nicht in die Konsole ein?
    Donnerstag, 15. September 2016 10:09
  • Hallo,

    wie hpotsirhc | Christoph schon angedeutet hat, ist das eher etwas für ein Script, welches man am besten in der Powershell_ise entwickelt. Das macht die Entwicklung viel einfacher.

    Mit der Annahme, dass Deine Daten in einer Datei mit dem Namen 'Datei.txt' stehen, sollte der Code dann ungefähr so aussehen:
    (den Pfad musst Du noch ergänzen!)

    $Inhalt = Get-Content -Path "<Pfad zur Textdatei>\Datei.txt"
    $SortierbarerInhalt = Foreach($Zeile in $Inhalt){
        $Zeile -match "(.+)((\d{2}\.){2}\d{4})" | Out-Null
        [PSCustomObject]@{
    	    Text = $Matches[1]
    	    Datum = Get-Date -Date $Matches[2]
        }
    }
    $SortierbarerInhalt | Sort-Object -Property Datum


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''



    Donnerstag, 15. September 2016 11:34
  • Was soll das "(.+)" in deinem Regex-Pattern? Damit werden doch nur beliebig viele Zeichen beliebiger Art selektiert. Das verstehe ich nicht.

    Freitag, 16. September 2016 06:18
  • Hast Du es mal probiert? Funktioniert's?  ;-) 

    Die Aufgabe war, die Texte anhand der enthaltenen Daten zu sortieren. Also fräse ich mir das Datum aus dem Text und mache beides, Text und zugehöriges Datum, als Object verfügbar. Dann kann man es hinterher beliebig weiterverarbeiten. Vielleicht bin ich damit übers Ziel hinausgeschossen, aber das ergibt ja eventuell sogar noch einen Mehrwert.


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''

    Freitag, 16. September 2016 17:36
  • > Damit werden doch nur beliebig viele Zeichen beliebiger Art selektiert. Das verstehe ich nicht.

    Das Regex Pattern lautet übersetzt: in dem gegebenen String können am Anfang beliebig viele Zeichen stehen (mindestens aber eines), aber am Ende müssen zwei Zahlen, ein Punkt, zwei Zahlen, ein Punkt, vier Zahlen stehen.

    Wenn man nur das Ende eines Strings sicher vorhersagen kann und keine Angaben über Länge und Beschaffenheit des restlichen Strings machen kann, kann man das genau so machen.

    Wovon ich aber abraten würde -außer man weiß ganz genau was man tut-, ist, Objekt-Arrays so zu erzeugen wie oben im Code. Also mit

    $SortierbarerInhalt = .... 
      


    So landet nämlich einfach alles was der Code dahinter an Ausgaben erzeugt, wirklich alles was nicht explizit einer Variable zugewiesen wurde im Array. Auch was mit z.B. write-output augegeben wird, oder Return-Codes etc.   Als Profi kann man das machen (auch wenn es wirklich nicht schön ist), bei Anfängern führt das schnell zu Problemen, wenn der Code erweitert wird.
    Also besser so:

    $Inhalt = Get-Content -Path "<Pfad zur Textdatei>\Datei.txt"
    $SortierbarerInhalt = New-Object System.Collections.Generic.List[object]
    
    Foreach($Zeile in $Inhalt){
        $Zeile -match "(.+)((\d{2}\.){2}\d{4})" | Out-Null
    	$newobj = [PSCustomObject]@{
    	    Text = $Matches[1]
    	    Datum = Get-Date -Date $Matches[2]
        }
    	$SortierbarerInhalt.Add($newobj)
    }
    
    $SortierbarerInhalt | Sort-Object -Property Datum
      

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Neu: Powershell Code Manager v5 ! Link
    (Schneller, besser + komfortabler scripten.)

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.



    Montag, 19. September 2016 13:24
    Moderator
  • Die Variante oben steht in meinem PoSh CodeManager unter 'New-Object -> Quick & Dirty'.  ;-)  ... aber ich hab Deine ordentliche Variante jetzt gleich darüber einsortiert.

    Danke


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''

    Dienstag, 20. September 2016 11:37
  • Na dann ist ja gut. ;-)

     
     


    Blog: http://bytecookie.wordpress.com

    Neu: Powershell Code Manager v5 ! Link
    (Schneller, besser + komfortabler scripten.)

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.



    Dienstag, 20. September 2016 11:46
    Moderator
  • Man könnte jetzt feststellen, dass wir am Ende wieder bei dem Skript sind, dass ich (auf Basis von psott's Lösung) gepostet hatte. In meinen Augen ist es nämlich ziemlich sinnlos, die Ausgabe des 

    $Zeile -match "(.+)((\d{2}\.){2}\d{4})" | Out-Null

    zu verwerfen, um sie dann über eine automatisch befüllte Variable von hinten durch die Brust ins Auge wieder hervorzuzaubern. Warum also nicht einfach, wie von mir geschrieben

    [Regex]::Match($zeile,"\d{2}\.\d{2}\.\d{4}").Value | Get-Date

    verwenden, damit man auch als nicht so erfahrener Nutzer noch weiß, wo der Wert herkommt?

    Und wo ist eigentlich der Fragesteller? Ist das Problem gelöst?

    • Bearbeitet hpotsirhc Mittwoch, 21. September 2016 06:01
    Mittwoch, 21. September 2016 06:00
  • Du scheinst verärgert. Ich frage mich warum. Du hast eine Alternative zu Psotts Code gepostet, Olaf hat eine Alternative zu deiner Lösung gepostet. Das darf hier jeder tun.

    Und du hast Recht, es ist für Anfänger besser nachvollziehbar, was mit den Match-Resultaten passiert, wenn man Sie direkt benutzt. Was ich daran wie du es dann gelöst hast, allerdings auch nicht so schön finde, ist das dann überall "00:00:00" mit in der Ausgabe steht. :-)

    Ergo: Es gibt halt immer noch was zu verbessern.
    Ich persönlich beschränke mich daher in der Regel darauf, die Dinge zu kommentieren, die entweder falsch sind oder bei denen ich großes Potential für Probleme beim OP und späteren Lesern sehe, wie in dem Fall des Arrays.
     
    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Neu: Powershell Code Manager v5 ! Link
    (Schneller, besser + komfortabler scripten.)

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.

    Mittwoch, 21. September 2016 11:17
    Moderator
  • Hallo Szabi_123,

    hier reicht eigentlich auch dieser Einzeiler

    gc 'c:\data.txt' | sort {get-date ([regex]::match($_,'\d{2}\.\d{2}\.\d{4}').Value)}

    Grüße Uwe






    • Als Antwort vorgeschlagen U333 Donnerstag, 22. September 2016 10:44
    • Nicht als Antwort vorgeschlagen U333 Donnerstag, 22. September 2016 10:44
    • Bearbeitet U333 Donnerstag, 22. September 2016 16:28
    Donnerstag, 22. September 2016 10:38