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-ID: 620767

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

Ausgedruckt am: 25.11.2024 um 10:11 Uhr

TK1987
Lösung TK1987 09.11.2020 aktualisiert um 16:53:44 Uhr
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
146189
Lösung 146189 09.11.2020 aktualisiert um 18:05:09 Uhr
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.
TheUnreal
TheUnreal 10.11.2020 aktualisiert um 07:46:39 Uhr
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]  
146189
Lösung 146189 10.11.2020 aktualisiert um 09:41:49 Uhr
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!!
TK1987
Lösung TK1987 10.11.2020 aktualisiert um 11:22:18 Uhr
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  
TheUnreal
TheUnreal 10.11.2020 um 14:23:55 Uhr
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!
TheUnreal
TheUnreal 05.01.2021 um 11:52:41 Uhr
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?
TK1987
Lösung TK1987 05.01.2021 aktualisiert um 12:13:49 Uhr
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
TheUnreal
TheUnreal 05.01.2021 um 13:20:09 Uhr
Goto Top
Danke, dann bin ich jetzt endlich auf dem richtigen Weg face-smile
TheUnreal
TheUnreal 18.01.2021 aktualisiert um 12:34:07 Uhr
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