Per Batch Wert aus einem HTML Code auslesen?
Hallo liebe Community!
Ich habe im Forum schon nach Lösungen gesucht, aber leider nur Bruchstücke der Lösung gefunden.
Ich habe schon mehrere Schritte per Batch realisiert, aber der letzte will mir nicht gelingen:
Ich habe ein Programm, welches in verschiedenen Versionen gestartet werden kann, die Version bestimmt sich nach der jeweiligen Datenbank und -version.
Dafür gibt es eine HTML Übersichtsseite die alle Datenbanken mit allen Versionen abbildet. Diese wird automatisch als Textdatei runtergeladen und aktualisiert.
Nun muss ich aus dem HTML Code die Zeile mit der richtigen Datenbank auslesen und anschließend die Version, die weiter hinten steht.
Beispiel
<tr><td class='subtd'>DB1</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'> VERSIONSNUMMER</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>
<tr><td class='subtd'>DB2</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'> VERSIONSNUMMER</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>
HINWEIS die Versionsnummer ist immer gleich aufgebaut, aber unterschiedlich lang XX.X.XXX ODER X.XX.XXXX
Ich würde mich riesig über eine Erklärung zur Lösung freuen, weil ich was dazu lernen möchte.
2 Antworten
Beinahe hätte ich ich geantwortet "No Way" (in Batch), ...damit meiner Regel "geht nicht gibts nicht" widersprochen.
Html-Zeilen gelten in Batch, wegen der "<" und ">" als giftige Strings und lassen sich in Batch nur mit riesigem Aufwand überhaupt handhaben.
Batch ist in Sachen unvorhersehbare Texte definitiv kein guter Partner .
Find/Findstr können lediglich feststellen ob ein String in einem Text vorhanden ist, können aber nur ganze Zeilen zurückgeben, jedoch kein Suchmuster selektiv zurückgeben.
Batch ist um definierte Abläufe zu Steuern, mehr aber auch nicht.
mit Powershell und einer kleinen RegEx ist das ein Klacks.
demo1.ps1
$String = "<tr><td class='subtd'>DB2</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'> 12.3.666</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>"
#gewagt! !!! im Lookbehind sind nur konstante Ausdrücke erlaubt!!! RegEx Lookbehind:(?<='14'\> ) =: (schau zurück ob "'14'>Leerzeichen" davor steht)
# suche zuvor: mindestens kein oder mehr Leerzeichen , mindestens eine Ziffer.mindestens eine Ziffer.mindestens eine Ziffer
$searchPattern="(?<='14'\> )\s*\d+\.\d+\.\d+"
#als Inputobjekt kan auch eien Datei dienen
Select-String $searchPattern -InputObject $String -AllMatches |%{
'Folgender Treffer gefunden :'
$_.matches.Value #alle Teffer anzeigen
#Zur Demo nur mal die komplete Match-Sruktur anzeigen
'Matchstruktur Demo:'
$_|fl *
}
pause
Ein RegEx-Lookbehind ist eine heiße Sache und man muss schon sehr Sicher sein, dass exakt das gewünschte vor dem eigentlichen Match steht!
Einfacher ist es erst die nähere Umgebung des "Ziels" (mit einer "ungefähren" Definition komplett zu erfassen, und in einem zweiten Schritt das genaue Match zu selektieren:
$String = "<tr><td class='subtd'>DB2</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'> 12.3.666</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>"
$BereichPattern = "width=.\d+.\s+height=.\d+.>\s*\d+\.\d+\.\d+\s*</font>"
$VersionPattern = "\d+\.\d+\.\d+"
$Version = Select-String $BereichPattern -InputObject $String -AllMatches |%{
$_.matches.Value|%{
Write-Host ('Folgender Bereich gefunden : {0}' -f $_) -fo green
Write-Host ('filtere VersionPattern: {0}' -f $VersionPattern) -fo green
(Select-String $VersionPattern -InputObject $_).matches.Value
}
}
$Version
pause
Natürlich ist das nur ein kleiner Teil , dessen was getan werden muss.
...und soll nur zeigen, wie man mit inhomogenem Text und RegEx auf die Suche geht.
Etwas muss auch für Dich übrig bleiben. Ob Du nun den perfekten Umgang mit der alten BatchSprache lernst, oder Dich gleich dem modernen PowerShell widmest macht im Lernaufwand den Kohl auch nicht fett.
In jedem Fall gibt es bei richtigem Umgang mit PS keine Probleme mit dem zu verarbeitendem Stoff.
Ich könnte Dir auch das ganze Ding schreiben, aber dann wär's Honorararbeit🤑... (Niemand arbeitet zum Spaß mit Datenbanken ergo machst Du solchen Quatsch für eine Firma?)
Ok mein Hund war Gassi und ich hab nichts weiter vor...:
Wenn Du in anderen Sprachen fit bist , kann ich mir sparen Kleinkram zu erklären.
Powershell ist extrem Flexibel was Variablen und Datentypen angeht. $DBTrefferZeilen kann ein String sein, oder aber eine Collection.
PS verwendet automatisch die Passende Methode für den Typ. gib Gas...
html.txt
<tr><td class='subtd'>DB1</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'>8.55.3</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>
<tr><td class='subtd'>DB2</td><td class='subtd'><nobr><font color=#fc7f2b><img title='Ich bin eine Datenbank' src='logo_ci.svg' width='14' height='14'> 6.777.12</font></nobr> <font color=grey title='Letztes Login (Monat.Jahr) auf dieser Datenbank'>XXX</font> </td></tr>
demo.ps1
$DBPatern="class='subtd'>DB1</td>" # Pattern für Zeilen mit Der gewünschten Datenbank (DB1)
$BereichPattern = "width=.\d+.\s+height=.\d+.>\s*\d+\.\d+\.\d+\s*</font>"
$VersionPattern = "\d+\.\d+\.\d+"
# datei einlesen und Zeilen auf den Datenbankpattern filtern
$DBTrefferZeilen=gc 'html.txt'|?{$_ -match $DBPatern}
#mal Anzeigen
$DBTrefferZeilen|%{ Write-Host ('DatenbankZeile gefunden: {0}' -f $_) -f blue}
#wieder der "Rundumblick" um die Versionsnummer
$Version = Select-String $BereichPattern -InputObject $DBTrefferZeilen -AllMatches |%{
$_.matches.Value|%{
Write-Host ('Folgender Bereich gefunden : {0}' -f $_) -fo green
Write-Host ('filtere VersionPattern: {0}' -f $VersionPattern) -fo green
(Select-String $VersionPattern -InputObject $_).matches.Value
}
}
$Version
switch ( $Version )
{ #Programm ausführen abhängig von Versionnummer
'8.55.3' { &'C:\mein Pfad\mein Programm' '"Parameter mit Spaces" blahOhne' }
'16.245.66' { &'C:\mein Pfad\anderes Programm'}
}
pause
Zur Lösung dieses Problems, ohne etwas an den Rahmenbedingungen zu ändern, musst du einen Regex verwenden, auch bekannt als regulärer Ausdruck. Damit kannst du ein Muster angeben, nachdem in einer Datei gesucht wird. Bestimmte Felder können damit auch ausgelesen werden. Du brauchst also ein Match auf die Zeile mit der richtigen Datenbank und dann matcht du die Versionsnummer in dieser Zeile.
Ok, ich bin jetzt so weit, dass ich weiß wie ich die Stelle suche lassen:
Findstr "'14'>.*</font>" Datenbankuebersicht.txt
.* müsste in dem Fall quasi der Platzhalter für die Version sein.
Aber wie mache ich jetzt ein Abfrage, in der er mir
1. Die Zeile mit der Datenbank sucht
Und 2. Den Wert für .* ausgibt?
DB1 oder DB2 als Variable in das Pattern und die Versionsnummer als gematchte Gruppe extrahieren. Vielleicht ist findstr aber auch etwas grob dafür. Mach sowas zum Glück nur unter Linux.
Erst einmal vielen Dank für die ganze Mühe und man bin ich froh über dein Mantra 😂
Um deine letzte Frage vorwegzunehmen: ich mach den Quatsch für mich innerhalb einer Firma 😅 unser Sysadmin hat die Ausführung jeder Exe geblockt, die nicht ge"whitelisted" ist.
Um mir meine Arbeit zu erleichtern, habe ich angefangen (während freier Spitzen) mit Boardmitteln Batch files zur Automatisierung zu schreiben.
Ich werde morgen mal deine Vorschläge versuchen umzusetzen 😅
Und ja ich weiß das Powershell wesentlich mächtiger ist, aber ich hab damit leider noch gar keine Erfahrung 😐
Bisher beschränkt sich mein Wissen auf SQL, C, C++ und eben Batch 😄