Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Aus Textdatei 4 nachfolgende Zeilen für mehrere Suchbegriffe in neue Datei schreiben

Frage Entwicklung Batch & Shell

Mitglied: servomonitor

servomonitor (Level 1) - Jetzt verbinden

28.05.2007, aktualisiert 30.05.2007, 5554 Aufrufe, 14 Kommentare

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
Mitglied: bastla
29.05.2007 um 00:35 Uhr
Hallo servomonitor und willkommen im Forum!

Ein erster Ansatz könnte so aussehen:
01.
@echo off & setlocal 
02.
set "Quelle=D:\Quelle.xml" 
03.
set "Ziel=D:\Ziel.xml" 
04.
set "Param=D:\Param.txt" 
05.
del "%Ziel%" 2>nul 
06.
set /a Zeile=0 
07.
for /f "usebackq delims=" %%i in ("%Quelle%") do call :ProcessLine "%%i" 
08.
goto :eof 
09.
:ProcessLine 
10.
set "Text=%~1" 
11.
set "Text=%Text:<=^<%" 
12.
set "Text=%Text:>=^>%" 
13.
set "Text=%Text:&=^&%" 
14.
if %Zeile% neq 0 goto :Schreiben 
15.
:Check 
16.
echo "%Text%"|findstr /c:"%%p" /g:"%Param%">nul && set /a Zeile=1 && echo %Text%>>"%Ziel%" 
17.
goto :eof 
18.
:Schreiben 
19.
set /a Zeile+=1 
20.
if %Zeile% gtr 5 set /a Zeile=0 & goto :Check 
21.
echo %Text%>>"%Ziel%" 
22.
goto :eof
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 "&":
{code:1 }[Edit] Aufgrund der im Kommentar unten von servomonitor geposteten xml-Datei "&"-Umwandlung oben eingearbeitet. [/Edit]
[Edit2] "Check"-Routine verbessert. [/Edit2]


Grüße
bastla
Bitte warten ..
Mitglied: Biber
29.05.2007 um 07:46 Uhr
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
Bitte warten ..
Mitglied: servomonitor
29.05.2007 um 09:49 Uhr
@bastla, vielen Dank mal für die Batch, ich werde diese testen, komme aber frühestens heute Nachmittag dazu.
@Biber: Hier nun der Anfang und das Ende der Datei. Die Parameter dazwischen unterscheiden sich im innerhalb der Datei durch eindeutige Parameternamen. Zeile 1 des Parameters beginnt mit <Symbol Name gefolgt vom Parameternamen (z.B. r2, p5), der Wert des Parameters steht in der zweiten Zeile
Meine Idee ist es, einige der Parameter anhand der Parameternummer in eine neue Datei zu schreiben, damit man diese relativ schnell überprüfen kann. Btw es handelt sich bei der Datei um Parameterfile für einen Motorregler.

servomonitor
01.
<?xml version = '1.0' encoding = 'windows-1252' standalone = 'yes'?> 
02.
<?xml-stylesheet type="text/xsl" href="umc_data.xsl"?> 
03.
 
04.
<!--The following Code declares the XML-Data-Syntax: --> 
05.
<!--End Syntaxdeclaration--> 
06.
 
07.
<!--Special characters: &amp = &, &lt = <, &gt = >, &quot = " --> 
08.
 
09.
 
10.
<!--XML Data:--> 
11.
 
12.
 
13.
<ISymbol> 
14.
   <Symbol Name = "r2" UDLSymbolIsActive = "True"> 
15.
      <Value Type = "VT_I2" Value = "45"/> 
16.
      <ESSymbolDescr Name = "r2" SymbolClass = "1"/> 
17.
      <Array Array = "False" ArrayElements = "0"/> 
18.
   </Symbol> 
19.
   <Symbol Name = "p5" UDLSymbolIsActive = "True"> 
20.
      <Value Type = "VT_UI2" Value = "2"/> 
21.
      <ESSymbolDescr Name = "p5" SymbolClass = "0"/> 
22.
      <Array Array = "False" ArrayElements = "0"/> 
23.
   </Symbol> 
24.
   <Symbol Name = "p6" UDLSymbolIsActive = "True"> 
25.
      <Value Type = "VT_I2" Value = "4"/> 
26.
      <ESSymbolDescr Name = "p6" SymbolClass = "1"/> 
27.
      <Array Array = "False" ArrayElements = "0"/> 
28.
   </Symbol> 
29.
 
30.
#### Hier folgen weitere Parameter##### 
31.
#### bis zum Ende der Datei 
32.
<Symbol Name = "p9899" UDLSymbolIsActive = "True"> 
33.
      <Value Type = "VT_UI4" Value = "0"/> 
34.
      <ESSymbolDescr Name = "p9899" SymbolClass = "0"/> 
35.
      <Array Array = "False" ArrayElements = "0"/> 
36.
   </Symbol> 
37.
</ISymbol> 
38.
<!--End XML-Data-->
Bitte warten ..
Mitglied: bastla
29.05.2007 um 10:00 Uhr
Hallo servomonitor!

Wie Deine Testdaten zeigen, ist zumindest auch das Zeichen "&" zu berücksichtigen (und inzwischen oben im Batch auch eingearbeitet) - bitte zum Testen daher die aktualisierte Version verwenden.

Grüße
bastla
Bitte warten ..
Mitglied: bastla
29.05.2007 um 10:18 Uhr
... Nachtrag:

Eine "Param.txt" zu Deinem obigen Beispiel könnte etwa so aussehen:
01.
"p5" 
02.
"r2" 
03.
"p9899"
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]
Bitte warten ..
Mitglied: servomonitor
29.05.2007 um 15:57 Uhr
@bastla, das klappt schon ganz gut. In der Datei sind allerdings auch Zahlenwerte mit Nachkommastellen. Diese werden unabhängig von der gesuchten Parameternummer bis zum Komma in die Ausgabedatei geschrieben, sind also nicht Teil der Suchliste. Der Nachkommateil und der Rest der Zeile geht aber verloren. Das Komma unterbricht also irgendwie die Verarbeitung. Gibt es hierfür ein Gegenmittel?

servomonitor

In der Quelldatei steht zum Beispiel:
<Symbol Name = "r26" UDLSymbolIsActive = "True">
<Value Type = "VT_R4" Value = "540,145"/>
<ESSymbolDescr Name = "r26" SymbolClass = "0"/>
<Array Array = "False" ArrayElements = "0"/>
</Symbol>

In der Ausgabedatei erscheint dann:
" ^<Value Type = "VT_R4" Value = "540"|findstr /c:"%p" /g:"C:\test\Param.txt">nul && set /a Zeile=1 && echo ^<Value Type = "VT_R4" Value = "540
obwohl r26 nicht als Suchoption angegeben ist.
Bitte warten ..
Mitglied: bastla
29.05.2007 um 16:40 Uhr
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:
01.
Const sQuelle = "D:\Quelle.xml" 
02.
Const sZiel = "D:\Ziel.xml" 
03.
Const sParam = "D:\Param.txt" 
04.
Set fso = CreateObject("Scripting.FileSystemObject") 
05.
If Not fso.FileExists(sQuelle) Then 
06.
	WScript.Echo "Quelldatei " & sQuelle & " nicht gefunden!" 
07.
	WScript.Quit(1) 
08.
End If 
09.
If Not fso.FileExists(sParam) Then 
10.
	WScript.Echo "Parameterdatei " & sParam & " nicht gefunden!" 
11.
	WScript.Quit(1) 
12.
End If 
13.
aParams = Split(fso.OpenTextFile(sParam, 1).ReadAll, vbCrLF) 
14.
Set oQuelle = fso.OpenTextFile(sQuelle, 1) 
15.
Set oZiel = fso.OpenTextFile(sZiel, 2, True) 
16.
Do While Not oQuelle.AtEndOfStream 
17.
	sText = oQuelle.ReadLine 
18.
	For i = 0 To UBound(aParams) 
19.
		If InStr(sText, aParams(i)) Then 
20.
			oZiel.WriteLine sText 
21.
			For j = 2 To 5 
22.
				If Not oQuelle.AtEndOfStream Then 
23.
					oZiel.WriteLine oQuelle.ReadLine 
24.
				Else 
25.
					WScript.Echo "Nicht genügend Datenzeilen für " & aParams(i) 
26.
				End If 
27.
			Next 
28.
			Exit For 
29.
		End If 
30.
	Next 
31.
Loop 
32.
oQuelle.Close 
33.
oZiel.Close 
34.
WScript.Echo "Done."
Speichern unter zB "Filtern.vbs" und per Doppelklick starten.

Grüße
bastla
Bitte warten ..
Mitglied: servomonitor
29.05.2007 um 17:29 Uhr
@bastla, das Skript erzeugt bei mir eine 1:1-Kopie der Quelldatei. Ich bekomme zweimal eine Msgbox "Nicht genügend Speicher für" ohne weitere Angabe. Nach zweimal OK erscheint dann "Done". Ergänzende Info: Die Quelldatei hat 14406 Zeilen. Das Einlesen in einem Rutsch könnte deshalb kritisch sein.
Woran scheitert eigentlich der Commandline-Ansatz? Welches Kommando sieht der Interpreter bei einem Komma?
servomonitor
Bitte warten ..
Mitglied: bastla
29.05.2007 um 18:48 Uhr
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.

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]
Bitte warten ..
Mitglied: Biber
29.05.2007 um 20:42 Uhr
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:
01.
@echo off & setlocal 
02.
set "Quelle=D:\Quelle.xml" 
03.
set "Ziel=D:\Ziel.xml" 
04.
 
05.
<b>set "Ziel=Con:"</b>  
06.
 
07.
del "%Ziel%" 2>nul 
08.
set /a Zeile=0 
09.
for /f "usebackq <b>skip=10</b> delims=" %%i in ("%Quelle%") do call :ProcessLine "%%i" 
10.
goto :eof 
11.
:ProcessLine 
12.
<b>Set text=%* 
13.
Set "Text=%Text:~1,-1%"</b> 
14.
set "Text=%Text:<=^<%" 
15.
set "Text=%Text:>=^>%" 
16.
set "Text=%Text:&=^&%" 
17.
 
18.
if %Zeile% neq 0 goto :Schreiben 
19.
:Check 
20.
echo "%Text%"|findstr /c:"%%p" /g:"%Param%">nul && set /a Zeile=1 && echo %Text%>>"%Ziel%" 
21.
goto :eof 
22.
~~~~~~ 
23.
:Schreiben 
24.
set /a Zeile+=1 
25.
if %Zeile% gtr 5 set /a Zeile=0 & goto :Check 
26.
echo %Text%>>"%Ziel%" 
27.
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:

01.
>TestServomonitorsXMLGeraffel.bat 
02.
   <Symbol Name = "p5" UDLSymbolIsActive = "True"> 
03.
      <Value Type = "VT_UI2" Value = "2"/> 
04.
      <ESSymbolDescr Name = "p5" SymbolClass = "0"/> 
05.
      <Array Array = "False" ArrayElements = "0"/> 
06.
   </Symbol> 
07.
<Symbol Name = "r26" UDLSymbolIsActive = "True"> 
08.
<b><Value Type = "VT_R4" Value = "540,145"/></b> 
09.
<ESSymbolDescr Name = "r26" SymbolClass = "0"/> 
10.
<Array Array = "False" ArrayElements = "0"/> 
11.
</Symbol> 
12.
<Symbol Name = "p9899" UDLSymbolIsActive = "True"> 
13.
      <Value Type = "VT_UI4" Value = "0"/> 
14.
      <ESSymbolDescr Name = "p9899" SymbolClass = "0"/> 
15.
      <Array Array = "False" ArrayElements = "0"/> 
16.
   </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
Bitte warten ..
Mitglied: bastla
29.05.2007 um 21:12 Uhr
@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
Bitte warten ..
Mitglied: servomonitor
30.05.2007 um 08:21 Uhr
@Biber
Die Batch funktioniert wunderbar, dauert zwar etwas länger als das VBS-Skript, aber es geht. Genau das hatte ich mit etwas weniger - oder auch mehr - Zeilen nie hingekriegt. Vielen Dank für die geniale Idee mit dem *.

@bastla
Die VBS funktioniert auch. Es lag an der Leerzeile am Ende der param.txt. Wie gesagt, ist das VBS schneller.

Das Ergebnis der beiden Skripte ist in jedem einzelnen Zeichen 1:1 identisch, so daß ich nur staunend Danke sagen kann. Das war sehr interessant und lehrreich für mich. Ich werde allerdings noch etwas Zeit brauchen, bis ich die verwendeten Befehle verstanden habe.

servomonitor
Bitte warten ..
Mitglied: bastla
30.05.2007 um 13:39 Uhr
Hallo servomonitor!

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 , werde aber gerne noch verbleibende Fragen zu klären versuchen. Wenn Du's selbst rausbekommst, ist es natürlich noch besser ...

Grüße
bastla
Bitte warten ..
Mitglied: Biber
30.05.2007 um 14:43 Uhr
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
Bitte warten ..
Neuester Wissensbeitrag
Humor (lol)

Linkliste für Adventskalender

(3)

Information von nikoatit zum Thema Humor (lol) ...

Ähnliche Inhalte
Heiß diskutierte Inhalte
Router & Routing
gelöst Ipv4 mieten (22)

Frage von homermg zum Thema Router & Routing ...

Windows Server
DHCP Server switchen (20)

Frage von M.Marz zum Thema Windows Server ...

Exchange Server
gelöst Exchange 2010 Berechtigungen wiederherstellen (20)

Frage von semperf1delis zum Thema Exchange Server ...

Hardware
gelöst Negative Erfahrungen LAN-Karten (19)

Frage von MegaGiga zum Thema Hardware ...