Aus Textdatei 4 nachfolgende Zeilen für mehrere Suchbegriffe in neue Datei schreiben
Hallo,
in einer Textdatei sind Werte im xml-Format gespeichert. Die einzelnen Parameter sind jeweils 5 Zeilen lang. In der ersten und dritten Zeile ist jeweils die Parameternummer hinterlegt. Zur einfachen Prüfung bestimmter Parameter möchte ich bestimmte Parameter in eine neue Textdatei schreiben.
Das Finden mittels findstr für liefert auch genau die beiden Zeilennummern z.B. 1244 und 1246. Wie kann man mittels Batch nur die Zeilen 1244-1248 in eine neue Textdatei schreiben? Alle bisher gefundenen Ansätze schreiben immer den Rest der Quell-Datei in die neue Datei. Das ganze sollte dann auch noch für ca. 15 andere Parameternummern erfolgen. Jeder Parameter tritt nur einmal in der Datei auf.
servomonitor
in einer Textdatei sind Werte im xml-Format gespeichert. Die einzelnen Parameter sind jeweils 5 Zeilen lang. In der ersten und dritten Zeile ist jeweils die Parameternummer hinterlegt. Zur einfachen Prüfung bestimmter Parameter möchte ich bestimmte Parameter in eine neue Textdatei schreiben.
Das Finden mittels findstr für liefert auch genau die beiden Zeilennummern z.B. 1244 und 1246. Wie kann man mittels Batch nur die Zeilen 1244-1248 in eine neue Textdatei schreiben? Alle bisher gefundenen Ansätze schreiben immer den Rest der Quell-Datei in die neue Datei. Das ganze sollte dann auch noch für ca. 15 andere Parameternummern erfolgen. Jeder Parameter tritt nur einmal in der Datei auf.
servomonitor
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 60004
Url: https://administrator.de/forum/aus-textdatei-4-nachfolgende-zeilen-fuer-mehrere-suchbegriffe-in-neue-datei-schreiben-60004.html
Ausgedruckt am: 23.04.2025 um 15:04 Uhr
14 Kommentare
Neuester Kommentar
Hallo servomonitor und willkommen im Forum!
Ein erster Ansatz könnte so aussehen:
Anpassen musst Du die Pfade für Quell-, Ziel- und Parameterdatei. In der Parameterdatei sind die gesuchten Parameter anzuführen, wobei jeder Parameter in einer eigenen Zeile stehen muss.
Da Du den Inhalt Deiner Quell-Datei nur schematisch beschrieben hast, sind vorläufig nur die Zeichen "<" und ">" als "Batch-Sonderzeichen" berücksichtigt. Sollten daneben auch zB "&" oder "|" vorkommen, müssten diese (siehe "set"-Zeilen nach ":ProcessLine") in weiteren Zeilen ebenfalls mit "^" maskiert werden - Beispiel für "&":
[Edit] Aufgrund der im Kommentar unten von servomonitor geposteten xml-Datei "&"-Umwandlung oben eingearbeitet. [/Edit]
[Edit2] "Check"-Routine verbessert. [/Edit2]
Grüße
bastla
Ein erster Ansatz könnte so aussehen:
@echo off & setlocal
set "Quelle=D:\Quelle.xml"
set "Ziel=D:\Ziel.xml"
set "Param=D:\Param.txt"
del "%Ziel%" 2>nul
set /a Zeile=0
for /f "usebackq delims=" %%i in ("%Quelle%") do call :ProcessLine "%%i"
goto :eof
:ProcessLine
set "Text=%~1"
set "Text=%Text:<=^<%"
set "Text=%Text:>=^>%"
set "Text=%Text:&=^&%"
if %Zeile% neq 0 goto :Schreiben
:Check
echo "%Text%"|findstr /c:"%%p" /g:"%Param%">nul && set /a Zeile=1 && echo %Text%>>"%Ziel%"
goto :eof
:Schreiben
set /a Zeile+=1
if %Zeile% gtr 5 set /a Zeile=0 & goto :Check
echo %Text%>>"%Ziel%"
goto :eof
Da Du den Inhalt Deiner Quell-Datei nur schematisch beschrieben hast, sind vorläufig nur die Zeichen "<" und ">" als "Batch-Sonderzeichen" berücksichtigt. Sollten daneben auch zB "&" oder "|" vorkommen, müssten diese (siehe "set"-Zeilen nach ":ProcessLine") in weiteren Zeilen ebenfalls mit "^" maskiert werden - Beispiel für "&":
set "Text=%Text:&=^&%"
[Edit2] "Check"-Routine verbessert. [/Edit2]
Grüße
bastla
Moin servomonitor,
willkommen im Forum auch von mir.
Eine Bitte hätte ich noch an Dich:
Auch wenn bastla und noch ein paar Skript-Künstler hier die von plastisch beschriebene XML-Datei bildhaft vor Augen sehen: Für diejenigen im Forum, die sowohl Problem wie auch Lösung nachvollziehbar [oder: Copy&Pastable] sehen wollen, wäre es nett eine (Beispiel-) XML-Datei oben in Deiner Eröffnungsfrage zu ergänzen.
Wäre das möglich?
Danke
Biber
willkommen im Forum auch von mir.
Eine Bitte hätte ich noch an Dich:
Auch wenn bastla und noch ein paar Skript-Künstler hier die von plastisch beschriebene XML-Datei bildhaft vor Augen sehen: Für diejenigen im Forum, die sowohl Problem wie auch Lösung nachvollziehbar [oder: Copy&Pastable] sehen wollen, wäre es nett eine (Beispiel-) XML-Datei oben in Deiner Eröffnungsfrage zu ergänzen.
Wäre das möglich?
Danke
Biber
... Nachtrag:
Eine "Param.txt" zu Deinem obigen Beispiel könnte etwa so aussehen:
Anmerkung zu den Anführungszeichen: Damit stellst Du sicher, dass exakte Übereinstimmung der Symbol-Namen vorliegen muss - eine Schreibweise r2 (also ohne Anführungszeichen) würde zB auch die Daten von "r25", "r237" oder "r2106" liefern - es würde also genügen, dass die Zeichenfolge r2 nur enthalten ist. Diese Möglichkeit könntest Du aber auch gezielt einsetzen, um zB mit r247 alle Symbole von r2470 bis r2479 (aber natürlich auch r247) anzusprechen.
Die Reihenfolge in der Zieldatei hängt übrigens von jener in der Quelldatei, nicht von der Reihenfolge in der "Param.txt" ab.
Grüße
bastla
[Edit] Schreibweise der Suchparameter genauer dargestellt. [/Edit]
Eine "Param.txt" zu Deinem obigen Beispiel könnte etwa so aussehen:
"p5"
"r2"
"p9899"
Die Reihenfolge in der Zieldatei hängt übrigens von jener in der Quelldatei, nicht von der Reihenfolge in der "Param.txt" ab.
Grüße
bastla
[Edit] Schreibweise der Suchparameter genauer dargestellt. [/Edit]
Hallo servomonitor!
Auf die Schnelle fällt mir nix Besseres ein, als die Sprache zu wechseln - wenn Du keine grundsätzlichen Einwände gegen VB-Script hast, versuch es einmal damit:
Speichern unter zB "Filtern.vbs" und per Doppelklick starten.
Grüße
bastla
Auf die Schnelle fällt mir nix Besseres ein, als die Sprache zu wechseln - wenn Du keine grundsätzlichen Einwände gegen VB-Script hast, versuch es einmal damit:
Const sQuelle = "D:\Quelle.xml"
Const sZiel = "D:\Ziel.xml"
Const sParam = "D:\Param.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists(sQuelle) Then
WScript.Echo "Quelldatei " & sQuelle & " nicht gefunden!"
WScript.Quit(1)
End If
If Not fso.FileExists(sParam) Then
WScript.Echo "Parameterdatei " & sParam & " nicht gefunden!"
WScript.Quit(1)
End If
aParams = Split(fso.OpenTextFile(sParam, 1).ReadAll, vbCrLF)
Set oQuelle = fso.OpenTextFile(sQuelle, 1)
Set oZiel = fso.OpenTextFile(sZiel, 2, True)
Do While Not oQuelle.AtEndOfStream
sText = oQuelle.ReadLine
For i = 0 To UBound(aParams)
If InStr(sText, aParams(i)) Then
oZiel.WriteLine sText
For j = 2 To 5
If Not oQuelle.AtEndOfStream Then
oZiel.WriteLine oQuelle.ReadLine
Else
WScript.Echo "Nicht genügend Datenzeilen für " & aParams(i)
End If
Next
Exit For
End If
Next
Loop
oQuelle.Close
oZiel.Close
WScript.Echo "Done."
Grüße
bastla
Hallo servomonitor!
Zum VB-Script: Stelle bitte sicher, dass es in der "Param.txt" keine Leerzeile (am Ende) gibt, da sonst jeder Vergleich eine "Übereinstimmung" liefert. Falls die Fehlermeldung "Nicht genügend Datenzeilen für" lauten sollte, wäre das ein Indiz für meine Vermutung.
Vielleicht hat Biber eine Idee dazu ...
Grüße
bastla
[Edit] Erklärungsansatz: Durch das "Zerschneiden" des Arguments ergibt sich eine ungerade Anzahl von Anführungszeichen, sodass das "echo" (in der Zeile nach ":Check") auch den Rest der Zeile als auszugebenden Text interpretiert. [/Edit]
Zum VB-Script: Stelle bitte sicher, dass es in der "Param.txt" keine Leerzeile (am Ende) gibt, da sonst jeder Vergleich eine "Übereinstimmung" liefert. Falls die Fehlermeldung "Nicht genügend Datenzeilen für" lauten sollte, wäre das ein Indiz für meine Vermutung.
Woran scheitert eigentlich der Commandline-Ansatz? Welches Kommando sieht der Interpreter bei einem Komma?
Kann ich auch noch nicht sagen; Tatsache ist, dass die Zeile dem Unterprogramm ":ProcessLine" zwar richtig übergeben wird, bei der Übernahme des Argumentes %1 aber beim Komma getrennt wird, wodurch bei Deinem Beispiel 145"/>" als %2 übergeben wird.Vielleicht hat Biber eine Idee dazu ...
Grüße
bastla
[Edit] Erklärungsansatz: Durch das "Zerschneiden" des Arguments ergibt sich eine ungerade Anzahl von Anführungszeichen, sodass das "echo" (in der Zeile nach ":Check") auch den Rest der Zeile als auszugebenden Text interpretiert. [/Edit]
Moin servomonitor und bastla,
ich stimme soweit mit bastlas Erklärungsansatz überein - hatte allerdings diesen Fall auch noch nicht (eine Kombination von XML-Tags und Text-in-Anführungszeichen-im-Text und Kommata)...
Anyhow - im Batch gibt es ja bekanntermaßen eine Lösung für (fast) alles.
bastlas CMD-Ansatz braucht nur winzige Anpassungen:
Der drei fett hervorgehobenen Stellen:
1. set "Ziel=Con:" --natürlich zum Testen nur auf den Monitor.
2. skip=10 die ersten 10 (oder so) Zeilen der XML-Datei, den Header kann ich ignorieren.
Sonst wird mir die Kommentarzeile [ "<!-- Special Characters...."] mit den vielen Kommata und den vielen Sonderzeichen mit ausgegeben.
Hab ich nicht näher untersucht warum... da fand ich das Skippen einfacher.
3. Set text=%*
Set "Text=%Text:~1,-1%"
Ich nehme nicht den ersten (und eigentlich einzigen Parameter) sondern "alle". *g
wenn ich "alle" übernehme und weiß, dass bei alle als erstes und letztes Zeichen ein " kommen MUSS... dann entsorge ich diese beiden Zeichen.
Das Ergebnis mit meiner aus den obigen Vorlagen zusammengestoppelten XML-Datei:
..as should do...
Aber dennoch... ist nicht sonderlich vollständig getestet: ob das nun beliebig viele Kommata verdaut... niemand weiß....
Oder anders formuliert: Für diesen Zweck ist Batch nicht das optimale Werkzeug.
Natürlich würde mich trotzdem interessieren, servomonitor, ob dieser bastla-variiert-von-Biber-Schnipsel deine ganze XML-Datei vertragen kann.
Gruß
Biber
ich stimme soweit mit bastlas Erklärungsansatz überein - hatte allerdings diesen Fall auch noch nicht (eine Kombination von XML-Tags und Text-in-Anführungszeichen-im-Text und Kommata)...
Anyhow - im Batch gibt es ja bekanntermaßen eine Lösung für (fast) alles.
bastlas CMD-Ansatz braucht nur winzige Anpassungen:
@echo off & setlocal
set "Quelle=D:\Quelle.xml"
set "Ziel=D:\Ziel.xml"
<b>set "Ziel=Con:"</b>
del "%Ziel%" 2>nul
set /a Zeile=0
for /f "usebackq <b>skip=10</b> delims=" %%i in ("%Quelle%") do call :ProcessLine "%%i"
goto :eof
:ProcessLine
<b>Set text=%*
Set "Text=%Text:~1,-1%"</b>
set "Text=%Text:<=^<%"
set "Text=%Text:>=^>%"
set "Text=%Text:&=^&%"
if %Zeile% neq 0 goto :Schreiben
:Check
echo "%Text%"|findstr /c:"%%p" /g:"%Param%">nul && set /a Zeile=1 && echo %Text%>>"%Ziel%"
goto :eof
~~~~~~
:Schreiben
set /a Zeile+=1
if %Zeile% gtr 5 set /a Zeile=0 & goto :Check
echo %Text%>>"%Ziel%"
goto :eof
Der drei fett hervorgehobenen Stellen:
1. set "Ziel=Con:" --natürlich zum Testen nur auf den Monitor.
2. skip=10 die ersten 10 (oder so) Zeilen der XML-Datei, den Header kann ich ignorieren.
Sonst wird mir die Kommentarzeile [ "<!-- Special Characters...."] mit den vielen Kommata und den vielen Sonderzeichen mit ausgegeben.
Hab ich nicht näher untersucht warum... da fand ich das Skippen einfacher.
3. Set text=%*
Set "Text=%Text:~1,-1%"
Ich nehme nicht den ersten (und eigentlich einzigen Parameter) sondern "alle". *g
wenn ich "alle" übernehme und weiß, dass bei alle als erstes und letztes Zeichen ein " kommen MUSS... dann entsorge ich diese beiden Zeichen.
Das Ergebnis mit meiner aus den obigen Vorlagen zusammengestoppelten XML-Datei:
>TestServomonitorsXMLGeraffel.bat
<Symbol Name = "p5" UDLSymbolIsActive = "True">
<Value Type = "VT_UI2" Value = "2"/>
<ESSymbolDescr Name = "p5" SymbolClass = "0"/>
<Array Array = "False" ArrayElements = "0"/>
</Symbol>
<Symbol Name = "r26" UDLSymbolIsActive = "True">
<b><Value Type = "VT_R4" Value = "540,145"/></b>
<ESSymbolDescr Name = "r26" SymbolClass = "0"/>
<Array Array = "False" ArrayElements = "0"/>
</Symbol>
<Symbol Name = "p9899" UDLSymbolIsActive = "True">
<Value Type = "VT_UI4" Value = "0"/>
<ESSymbolDescr Name = "p9899" SymbolClass = "0"/>
<Array Array = "False" ArrayElements = "0"/>
</Symbol>
..as should do...
Aber dennoch... ist nicht sonderlich vollständig getestet: ob das nun beliebig viele Kommata verdaut... niemand weiß....
Oder anders formuliert: Für diesen Zweck ist Batch nicht das optimale Werkzeug.
Natürlich würde mich trotzdem interessieren, servomonitor, ob dieser bastla-variiert-von-Biber-Schnipsel deine ganze XML-Datei vertragen kann.
Gruß
Biber
@servomonitor
... und ob's hinsichtlich der VBS-Variante tatsächlich an der "Param.txt" lag ...
@Biber
Die Idee hatte ich zwar, aber %* wollte mir beim besten Willen nicht einfallen (obwohl ich es schon einmal bei einem Deiner OEvres gesehen hatte).
Grüße
bastla
... und ob's hinsichtlich der VBS-Variante tatsächlich an der "Param.txt" lag ...
@Biber
Die Idee hatte ich zwar, aber %* wollte mir beim besten Willen nicht einfallen (obwohl ich es schon einmal bei einem Deiner OEvres gesehen hatte).
Grüße
bastla
Hallo servomonitor!
Freut mich, dass es klappt.
, werde aber gerne noch verbleibende Fragen zu klären versuchen. Wenn Du's selbst rausbekommst, ist es natürlich noch besser ...
Grüße
bastla
Freut mich, dass es klappt.
Ich werde allerdings noch etwas Zeit brauchen, bis ich die verwendeten Befehle verstanden habe.
Ich muss zugeben, dass ich sehr sparsam kommentiert habe Grüße
bastla
Sagen wir so...
Wenn bastla und ich auch noch kommentiert hätten, dann wäre es ja ein Tutorial geworden.. *gg
Auch ich stehe natürlich für Nachfragen zur Verügung.
Allerdings werde ich, falls hier im Beitrag in den nächsten paar Tagen keine Aktivitäten mehr zu verzeichnen sind, diesen ja bereits "gelösten" Beitrag schließen.
Grundsätzlich ist diese spezielle Konstellation von Zeilen in einer Inputdatei auch so exotisch, dass ich gar nicht wüsste,
unter welchem Stichwort ich so etwas "wiederfindbar" ablegen sollte.
"Wenn von einer FOR-Anweisung nur ein Parameter als String in Anführungszeichen an einen CALL-Block übergeben wird,
dort aber mehrere Parameter ankommen, weil im übergebenen String Kommas enthalten sind, dann..."
---> Hört sich ziemlich speziell an.....wäre nicht der Bringer auf einer Grillparty
Grüße
Biber
Wenn bastla und ich auch noch kommentiert hätten, dann wäre es ja ein Tutorial geworden.. *gg
Auch ich stehe natürlich für Nachfragen zur Verügung.
Allerdings werde ich, falls hier im Beitrag in den nächsten paar Tagen keine Aktivitäten mehr zu verzeichnen sind, diesen ja bereits "gelösten" Beitrag schließen.
Grundsätzlich ist diese spezielle Konstellation von Zeilen in einer Inputdatei auch so exotisch, dass ich gar nicht wüsste,
unter welchem Stichwort ich so etwas "wiederfindbar" ablegen sollte.
"Wenn von einer FOR-Anweisung nur ein Parameter als String in Anführungszeichen an einen CALL-Block übergeben wird,
dort aber mehrere Parameter ankommen, weil im übergebenen String Kommas enthalten sind, dann..."
---> Hört sich ziemlich speziell an.....wäre nicht der Bringer auf einer Grillparty
Grüße
Biber