theunreal
Goto Top

Powershell array.Indexof("string") will nicht

Hallo zusammen,

ich habe einen Emailtext, den ich umfangreich manipulieren muss, da die Sender sich da nicht so an die Konventionen halten können face-smile.
Bisher habe ich im Textbody oder htmlbody über Substring und index gesucht und alles gefunden, was ich immer so haben wollte.

Da ich aber endlich verstanden habe wie arrays funktionieren und wofür die so gut sein können, habe ich gedacht ich lese den Text ab jetzt in ein Array ein,
kann gezielt Zeilen manipulieren und alles zusammen in gleicher Reihenfolge wieder zurückschreiben face-smile

Nun möchte ich den Index mit "Kaufdatum" finden um diesen gezielt umzuschreiben, aber ich bekomme immer ein false zurück.

function rebuildDate()
{

   $hmtlArray = $modTXT.Split("`n")  
   $test = $hmtlArray -match("Kaufdatum")  
   write-host $test
    

 Write-Host "Ich bin eine Wartemarke"  
}

$test ist -1 die Originalzeile heißt auch "Kaufdatum 12-22-2019". Da ich nun aber nicht weiß, was hinter Kaufdatum so kommt müsste ich nach "Kaufdatum*" suchen, aber das geht auch nich...

Hilfe, bitte face-smile

Gruß Sascha

Content-Key: 620767

Url: https://administrator.de/contentid/620767

Printed on: April 20, 2024 at 00:04 o'clock

Member: TK1987
Solution TK1987 Nov 09, 2020 updated at 15:53:44 (UTC)
Goto Top
Moin,

Die .IndexOf()-Methode erfordert immer die gesamte exakte Zeile.
$htmlArray.IndexOf($htmlArray -match 'Kaufdatum')  
Ggfs, falls die Zeichenkette mehrfach vorkommt, solltest du den Matchstring noch mit Regex erweitern, da andernfalls nur der erste Fund berücksichtigt wird.

Eine andere Möglichkeit: Einfach den gesamten Array mit Regex-Replace abändern. So benötigst du den Index erst gar nicht.

Gruß Thomas
Mitglied: 146189
Solution 146189 Nov 09, 2020 updated at 17:05:09 (UTC)
Goto Top
Zitat von @TK1987:
Eine andere Möglichkeit: Einfach den gesamten Array mit Regex-Replace abändern. So benötigst du den Index erst gar nicht.
Jepp, oder als weitere Alternative, da es ja sowieso schon in HTML ist und damit hervorragend von einem Parser verarbeitet werden kann dieses in ein DOM Object zu laden und dann mit den üblichen DOM-Methoden gezielt den Inhalt der Tags zu verändern und anschließend das generierte HTML wieder auszugeben, einfaches Beispiel:
$html = @'  
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
<title>Das ist ein HTML Dokument</title>
</head>
<body>
<div id="elKaufdatum">BlaBlablub Text</div>  
</body>
</html>
'@  

$dom = New-Object -Com htmlfile
$dom.IHTMLDocument2_write($html)
$dom.getElementById('elKaufdatum').innerText = 'Neuer Text'  
$dom.documentElement.innerHTML
Dann muss man als Laie auch nicht mit Regex rum hantieren.
Member: TheUnreal
TheUnreal Nov 10, 2020 updated at 06:46:39 (UTC)
Goto Top
Vielen Dank für die Ansätze!

Regex habe ich mir schon ein paar mal angeschaut, aber noch kapiere ich das nicht so wirklich. Habt Ihr da vielleicht einen Link zu einem (guten) Tutorial? Hab im Blog von Stefan Rehwald schon einiges gelesen - allerdings sind die gegebenen Beispiele oft so vereinfacht, dass ich keinen Bezug zu meiner (komplizierten) Realität herstellen kann face-smile.

Die DOM Funktion schaue ich mir ebenfalls nochmal an, danke dafür. Aktuell bearbeite ich den HTMLBody einer Email und wandle den mittels replace aufwendig in einfachen Text um. Vermutlich schieße ich vom Knie durch den Bauch ins Auge^^

Da ich in 150 Emails festgestellt habe, dass die Positionen immer gleich sind (Template) habe ich auch immer den richtigen Index.
Das mag jetzt als "Quick´n Dirty" helfen, aber auf Dauer ist das nichts. Immerhin könnte auch jemand mal eine Zeile vergessen....

 $aDate = $hmtlArray[15]
                            $aDate = $aDate.Trim()
                            $aDate = $aDate.TrimStart("Kaufdatum")  
                            $aDate = $aDate.Trim()
                            $aDate = $aDate.split("-")  
                            [int]$i = 0
# Salesdate kommt leider mal 3/15/2020 statt 03, also müssen wir auffüllen damit dieWweiterverarbeitung passt.
                                                        foreach ($a in $aDate){
                                                                if ($a.length -le 1) {        
                                                                    $adate[$i] = "0" + $a  
                                                                    Write-Host $aDate[$i]
                                                                    $i++
                                                                }else{
                                                                    Write-Host "Nö"  
                                                                }           
                                                        }
                         
                            $hmtlArray[15] = [string]"Kaufdatum   " + $adate[2] + "-" +$adate + "-" + $adate[1]  
Mitglied: 146189
Solution 146189 Nov 10, 2020 updated at 08:41:49 (UTC)
Goto Top
Regex habe ich mir schon ein paar mal angeschaut, aber noch kapiere ich das nicht so wirklich. Habt Ihr da vielleicht einen Link zu einem (guten) Tutorial?
Das ist eigentlich sehr leicht verständlich zu lesen: Regular Expressions Tutorial
Vermutlich schieße ich vom Knie durch den Bauch ins Auge^^
Definitiv!!
Member: TK1987
Solution TK1987 Nov 10, 2020 updated at 10:22:18 (UTC)
Goto Top
Nachdem du das von @146189 verlinkte Tutorial mal abgearbeitet hast...

Zitat von @TheUnreal:
Salesdate kommt leider mal 3/15/2020 statt 03, also müssen wir auffüllen damit die Weiterverarbeitung passt.
Dafür hättest du deinen Raw-String gar nicht in ein Array zerlegen müssen.

Einfaches Beispiel:
$modTXT -Match 'Kaufdatum (\d+).(\d+).(\d+)' | Out-Null  
Wir überprüfen deinen Raw-String mit -Match auf die gesuchte Regex-Zeichenfolge.

Wie du siehst, habe ich anschließend die Ausgabe mit Out-Null gelöscht. Wieso das?!
Match hat die besondere Eigenschaft, gefundene Zeichenfolgen in die Variable $Matches zu schreiben.

Wenn wir uns diese nun ansehen, finden wir dort auch unsere Gruppierungen wieder:
PS C:\> $Matches

Name                           Value
----                           -----
3                              2020
2                              15
1                              3
0                              Kaufdatum 3/15/2020

Hiermit können wir nun ganz leicht unser Datum so ausgeben lassen, wie wir es gerne hätten.
$Kaufdatum = get-date -day $Matches.2 -month $Matches.1 -year $Matches.3 -format 'yyyy-MM-dd'  
Nun brauchen wir nur noch das alte Datum durch das neue ersetzen
$modTXT -Replace '(?<=Kaufdatum )\d+.\d+.\d+',$Kaufdatum  
Member: TheUnreal
TheUnreal Nov 10, 2020 at 13:23:55 (UTC)
Goto Top
Nochmal vielen Dank an euch alle. Ich werde mir ddas Tutorial gleich ansehen, nun ist Luft dafür.
Danke auch nochmal an TK für das Beispiel. Ich hoffe doch, dass es auf fruchtbaren Boden fällt face-smile!
Member: TheUnreal
TheUnreal Jan 05, 2021 at 10:52:41 (UTC)
Goto Top
Ich verstehe es noch immer nicht. Dein Beispiel funktioniert, klar.

Wenn ich mir deinen RegEx Ausdruck anschaue, sehe ich nach Studium des Tutorials von Danielfett.de :

Du maskierst das d,
(\d...)
das bedeutet also d hat eine besondere Funktion (Dezimalzahl), d darf mindest einmal noch vorkommen
(\d+...)
.
Die nächste Zahl liegt hinter einem Punkt
(\d+).(...)

Was ich aber nicht verstehe ist, warum er den String korrekt zerlegt, wenn ich keinen Punkt drin habe. Müsste es nicht fehlerhaft laufen, wenn das Datum anders getrennt ist?

Nein, muss es nicht, weil es kein Punkt ist, sondern ein Platzhalter für ein beliebiges Zeichen...

Habe ich das korrekt verstanden?
Member: TK1987
Solution TK1987 Jan 05, 2021 updated at 11:13:49 (UTC)
Goto Top
Zitat von @TheUnreal:
Nein, muss es nicht, weil es kein Punkt ist, sondern ein Platzhalter für ein beliebiges Zeichen...

Habe ich das korrekt verstanden?
Jup.

Wenn du willst, das wirklich nur Punkte zerlegt werden, müsstest du den Punkt escapen, also \. verwenden.

Gruß Thomas
Member: TheUnreal
TheUnreal Jan 05, 2021 at 12:20:09 (UTC)
Goto Top
Danke, dann bin ich jetzt endlich auf dem richtigen Weg face-smile
Member: TheUnreal
TheUnreal Jan 18, 2021 updated at 11:34:07 (UTC)
Goto Top
Haha....danke nochmal,

Nun habe ich es endlich stichfest. Denn es gab mal 3 mal 5 mal 2 Leerzeichen usw. Aber nun Matched es und liefert das ergebnis, dass ich haben möchte face-smile

Oder sieht jemand einen groben Fehler? --Ja ich grad...warum matched größer als 12 auch wenn es nur 6 ist?

function CheckSalesDate(){
 
    $modTXT -Match 'Kaufdatum(\s+)(\d+).(\d+).(\d+)' | Out-Null                              
    #Da manche im Mailtemplate verschlimmbessern prüfen wir das Trennzeichen des Datums (. oder /)
       if ($Matches -like "*/*"){  
                 #Ok...hier sollte also US Datum kommen, aber falls nicht, dann Brechstange...
                 #Wenn Matches.2 größer als 12 ist, wird es wohl doch europäisch sein...
                if ($Matches[2] -gt 12){
                    $Kaufdatum = Get-Date -Day $Matches[2] -Month $Matches[3] -Year $Matches[4] -Format "yyyy-MM-dd"  
                }else{
                    $Kaufdatum = Get-Date -Day $Matches[3] -Month $Matches[2] -Year $Matches[4] -Format "yyyy-MM-dd"  
                }
       }else{
        #Wenn Punkte, dann klar Europäisch
        $Kaufdatum = Get-Date -Day $Matches[2] -Month $Matches[3] -Year $Matches[4] -Format "yyyy-MM-dd"  
       }
       #$modTXT -replace ';[^\r\n]*',''  
    $modTXT = $modTXT -Replace '(?<=Kaufdatum(\s+))\d+.\d+.\d+', $Kaufdatum  
}

Hier gehts weiter :
PS- array springt, if condition greift immer