lowered
Goto Top

Mit batch-script wert in b.txt durch wert aus a.txt ersetzen

Ersetzen eines Parameters an einer bestimmten Stelle in einer txt-Datei durch einen Parameter aus einer anderen txt-Datei

Hallo die Damen und Herren,
ich beschäftige mich betriebsbedingt mit Batch-Script. Genutzt wird es für eine Programmkopplung, also Programme ausführen und Werte aus Dateien hin und her kopieren. Genau da liegt auch das Problem.

Also, Werte aus Dateien auslesen schaffe ich mittlerweile schon.
Ich sitze seit 3 Tagen daran, in einer Datei Lag1.ein 5 Parameter zu ändern. Wenn ich einen schaffe, geht der rest ja von alleine.

Strategie:
die Zeile mit dem Parameter den ich ändern möchte aus Lag1.ein mit find auslesen>> var1=FRX = 134.45
Den neuen Wert lese ich aus der Datei Lagerkraft.txt aus>> kra1=FRX = 3455.34

Ich habe eine Funktion gefunden, die nun die Datei Lag1.ein zeilenweise ausliest und mit var1 vergleicht. wenn die Zeile ungleich var1 ist wird sie in eine datei Lag11.ein kopiert
Ist die Zeile = var1, wird var1 durch kra1 ersetzt und in Lag11.ein kopiert ...

Offensichtlich gibt es da aber probleme mit den Leerzeichen innerhalb der Variablen, das Ergebnis des Ersetzens ist:
= 134.45 FRX = 3455.34 = 134.45 (hab die Zeichenfolge nicht ganz genau im Kopf)

Meinen Code kann ich erst morgen Nachmittag posten, der liegt leider noch auf Arbeit.

Aber vielleicht hat jemand eine Idee was mein Problem ist. Ich gehe davon aus das mir lediglich Klammern, Anführungszeichen oder ähnliches fehlen um den ganzen 'String' zu vergleichen bzw zu ersetzen.


Für Hilfe bin ich sehr dankbar, damit ich mit meiner Bachelorarbeit endlich mal wieder vorrankomme.


Grüße

H. Esche

Content-Key: 148654

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

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

Member: bastla
bastla Aug 09, 2010 at 17:27:28 (UTC)
Goto Top
Hallo Lowered und willkommen im Forum!

Ließe sich die Beschreibung auch so darstellen?
Lagerkraft.txt:
Zeile L1
FRX = 3455.34
...
Zeile Lx
lag1.ein Ist:
Zeile 1
FRX = 134.45
...
Zeile x
lag1.ein Soll:
Zeile 1
FRX = 3455.34
...
Zeile x
Grüße
bastla
Member: Lowered
Lowered Aug 09, 2010 at 18:09:16 (UTC)
Goto Top
bei der Datei Lagerkraft ist alles möglich, diese erstelle ich selbst aus Ansys. Allerdings wäre mir die Matrixschreibweise "lieber" um die Werte zuordnen zu können. Ich habe im Ansys ein Getriebe, dort werte ich an jedem Lager Kräfte und Biegung aus. Wie ich die ausgebe, bleibt mir überlassen.
Lagerkraft.txt
Zeile L1
FRX = 3455.34
FRY = ...
...

Zeile L2
FRX = ....

Zeile L3
da ist "alles" möglich, solange es irgendwie übersichtlich bleibt.

bei der lag1.ein ist das nicht möglich. Das ist eine Eingabedatei für ein Fortran Programm, da gibt es eine bestimmte Struktur:
Lag1.ein
$Lagerdaten
...
$Darstellung
...
$Lagerkraefte
FRX = 134.45
FRY = ...
...
$Ende

Wie gesagt ich habe die Werte die ich will schon als Parameter, nur beim ersetzen läuft da etwas durcheinander. Ich Poste morgen die Dateien, sowie das Batch-Script.
Sofern es schnellere, bessere Lösungen gibt, bin ich natürlich offen.

Danke @ bastla
Member: bastla
bastla Aug 09, 2010 at 18:26:59 (UTC)
Goto Top
Hallo Lowered!

Nach Deiner Darstellung könnte es in "Lagerkraft.txt" mehrere Zeilen mit "FRX =" geben - welche wäre dann zu verwenden?

Ansonsten warte ich mal auf morgen ...

Grüße
bastla
Member: Lowered
Lowered Aug 10, 2010 at 13:42:40 (UTC)
Goto Top
So, los geht es.

derzeit sieht die datei LAgerkraft wie folgt aus:

L1;103926.46;      0.00;      0.00;
L2;101059.69;     15.31;  27690.71;
L3;124402.50;     -3.28; -27924.22;
L4; 93513.70;     -0.04;      0.00;
> 
Das ist beliebig änderbar. Der Inhalt ist (jetzt) eine Tabelle die für jede Lagerstelle die Kraft FRX, FRY und FRZ enthält. Wenn das hilft, könnte man jeder Variable noch eine Nummer anfügen für die Lagerstelle, sprich FRX1 ...

Die Datei Lag1.ein sieht immer folgendermaßen aus:
$ Lagerbelastung

DREHZAHL = 1800
FRX = 1234
FRY = 69529
FAZ = 0
WBETA =  0.0
WGAMMA = 0.0

$ Ende
> 
halt mit unterschiedlichen Zahlenwerten, aber die Variablen heißen gleich. Lag[Nr].ein gibt es für jede Lagerstelle, wird später noch umbenannt und in ein anderes Verzeichnis kopiert, aber das ist ja nicht schwer.

Jetzt habe ich mir folgendes zusammengefummel:

@ECHO off
SETLOCAL enabledelayedexpansion

REM Suchen der Lagerkraft aus datei

find "L1" Lagerkraft.txt > temp1.txt  
for /f "tokens=2 delims=;" %%A in (temp1.txt) do set kra1=FRX = %%A  

REM Suchen und Ersetzen in einer Textdatei

FOR /F "tokens=*" %%B in ('find "FRX" Lag1.ein') DO SET var1=%%B  

SET "quell_datei=Lag1.ein"  
SET "ziel_datei=Lag11.ein"  

REM Ausgabe einer Fehlermeldung und Programmabbruch
REM falls die Variable "suchen_nach" nicht definiert ist  
IF NOT DEFINED var1 (ECHO Fehler: Die Variable suchen_nach nicht definiert^^!&GOTO :eof)

REM Loeschen der Ausgabedatei, falls sie (noch) existiert
IF EXIST %ziel_datei% (DEL /f %ziel_datei% 1>NUL 2>NUL)

REM Quell-Datei zeilenweise auslesen 
REM und in Variable "zeile" schreiben  
FOR /f "delims=*" %%i IN ('FINDSTR . "%quell_datei%"') DO (  
SET zeile=%%i& CALL :ersetzen !zeile!
)
GOTO :weiter
:ersetzen
REM innerhalb der Variable "zeile"  
REM den Inhalt der Variable "suchen_nach" suchen  
REM und diese durch den Inhalt der Variable "ersetzen_durch" ersetzen  
SET zeile=!zeile:%var1%=%kra1%!

REM Inhalt der Variable "zeile" in die Ausgabedatei schreiben  
IF [!zeile!] EQU  (ECHO.>>%ziel_datei%) ELSE (ECHO !zeile!>>%ziel_datei%)
GOTO :eof

:weiter
REM weitere Verarbeitung
> 

Das ganze findet erstmal in einem Ordner statt. Ich lese den Wert für FRX aus der Datei Lagerkraft aus und lege ihn in %kra1 ab.
Ich suche in Lag1.ein die Zeile in der FRX = ... steht und speichere den Inhalt der Zeile in %var1

Quelldatei ist Lag1.ein
Zieldatei ist Lag11.ein

Dann wird alles bis FRX sauber von Quell- in Zieldatei kopiert. In der Zeile von FRX steht dann:
-23077=FRX = 103926.46= -23077
Danach wird wieder suaber kopiert.

Mein Verdacht: der Vergleich der beiden Strings funktioniert wegen der enthaltenen Leerzeichen nicht.

Anschließend muss ich noch die anderen (bisher) 2 Parameter ändern. Das werde ich vermutlich alles auf einmal machen.

Für einen Augenblick habe ich schon drüber nachgedacht Lag1.ein bis FRX zu kopieren und danach die die Werte hart in die Datei reinzuschreiben. Allerdings würde ich mir die Kontrollmöglichkeit durch das auslesen und vergleichen gern offen halten.

Oder gibt es noch bessere Verfahren / Möglichkeiten mittels Batch?
Habe mir angelesen das das Umkopieren dringend zu empfehlen ist, da es sonst zu Datenverlust kommen könnte.

Dann bin ich jetzt mal gespannt wie sich das ganze entwickelt.
Member: bastla
bastla Aug 10, 2010 at 16:08:27 (UTC)
Goto Top
Hallo Lowered!

Ich würde es geringfügig anders anlegen (und dabei gleich für "Lag2.ein", "Lag3.ein", etc - können dann über eine weitere Schleife verarbeitet werden - vorsorgen):
@echo off & setlocal
set "quell_datei=Lag1.ein"  
set "lager=Lagerkraft.txt"  

REM Dateinamen (mit Pfad, aber ohne Typ) ermitteln
for %%i in ("%quell_datei%") do set "quell_datei_n=%%~dpni"  
REM Dateinummer (=letzte Stelle des Namens) ermitteln
set "quell_datei_nr=%quell_datei_n:~-1%"  
REM Zieldateinamen erzeugen
set "ziel_datei=%quell_datei_n%1.ein"  

REM FR* entsprechend der Dateinummer auslesen (dabei Leerzeichen entfernen) und den Variablen %X%, %Y% und %Z% zuweisen
for /f "tokens=2-4 delims=; " %%a in ('findstr /b "L%quell_datei_nr%;" "%lager%"') do set "X=FRX = %%a" & set "Y=FRY = %%b" & set "Z=FRZ = %%c"  

REM Loeschen der Ausgabedatei
del /f "%ziel_datei%" 2>nul  

REM Quell-Datei zeilenweise auslesen, in Variable %zeile% schreiben und Verarbeitungs-Unterprogramm aufrufen
for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "%quell_datei%"') do set "zeile=%%j" & call :ProcessLine  
GOTO :weiter

:ProcessLine
REM Auf FR*-Zeile prüfen und ggf ersetzen
if defined zeile for %%a in (X Y Z) do echo %zeile%|findstr /b /c:"FR%%a =">nul && (echo %%a & call set "zeile=%%%%a%%")  
REM Zeile in Zieldatei schreiben
>>"%ziel_datei%" echo\%zeile%  
GOTO :eof

:weiter
REM weitere Verarbeitung
Ev ist
call set "zeile=%%%%a%%"
etwas erklärungsbedürftig: Damit wird der Variablen %zeile% je nach Inhalt von %%a der Variableninhalt von %X% oder %Y% oder %Z% zugewiesen - zur Veranschaulichung durch "_" getrennt geschrieben sähe der letzte Teil so aus: %%_%%a_%%, woraus wegen des "call" dann eben (jetzt wieder ohne Trennzeichen) zB %X% wird ...

Grüße
bastla
Member: Lowered
Lowered Aug 11, 2010 at 14:39:41 (UTC)
Goto Top
Erfolgsmeldung!

Das Script funktioniert super. Habe noch ein paar kleine Änderungen vorgenommen um weitere Variablen einzulesen.

Recht herzlichen Dank für die Mühe @bastla
Member: bastla
bastla Aug 11, 2010 at 16:23:58 (UTC)
Goto Top
Hallo Lowered!

Freut mich, wenn's passt ... face-smile

Grüße
bastla

P.S.: "Mühe" war dabei nicht im Spiel ... face-wink
Member: Lowered
Lowered Aug 12, 2010 at 13:02:40 (UTC)
Goto Top
Hallo, ich nochmal.

habe Heute nochmal ein wenig daran rumgebastelt um das Ganze besser portierbar zu machen. Also habe ich versucht die absoluten Pfadangaben in Variablen zu packen, mit dem Ergebnis, das jetzt an den Stellen FRX, FRY und FAZ nichts mehr geschrieben wird.


@echo off & setlocal

REM Dateipfade müssen angepasst werden!!!
REM Pfad für Dateien
set "dat=H:\Lagerkram\Testlauf2\Dateien\"  

REM Pfad zu LAGER2HP
set "lag=H:\Lagerkram\Testlauf2\Lager2\"  

REM Pfad zu ANSYS
set "ans="  


set /p "anzahl="<"%dat%Lagerzahl.txt"  
set "nr=1"  

cd /D %dat%

set "lager=%dat%Lagerkraft.txt"  
REM Zieldateinamen erzeugen
set "ziel_datei=%lag%work\Lager2.ein"  

:anfang

cd /D %dat%

set "quell_datei=%dat%Lag%nr%.ein"  

REM Dateinamen (mit Pfad, aber ohne Typ) ermitteln
for %%i in ("%quell_datei%") do set "quell_datei_n=%%~dpni"  
REM Dateinummer (=letzte Stelle des Namens) ermitteln
set "quell_datei_nr=%quell_datei_n:~-1%"  

REM FR* entsprechend der Dateinummer auslesen (dabei Leerzeichen entfernen) und den Variablen %X%, %Y% und %Z% zuweisen
for /f "tokens=2-4 delims=;" %%a in ('findstr /b "%quell_datei_nr%;" "%lager%"') do set "X=FRX = %%a" & echo %X% & set "Y=FRY = %%b" & set "Z=FAZ = %%c"  


REM Loeschen der Ausgabedatei
del /f "%ziel_datei%" 2>nul  

REM Quell-Datei zeilenweise auslesen, in Variable %zeile% schreiben und Verarbeitungs-Unterprogramm aufrufen
for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "%quell_datei%"') do set "zeile=%%j" & call :ProcessLine  
GOTO :weiter

:ProcessLine
REM Auf FR*-Zeile prüfen und ggf ersetzen
if defined zeile for %%a in (X Y) do echo %zeile%|findstr /b /c:"FR%%a =">nul && (echo %%a & call set "zeile=%%%%a%%")  
if defined zeile for %%a in (Z) do echo %zeile%|findstr /b /c:"FA%%a =">nul && (echo %%a & call set "zeile=%%%%a%%")  
REM Zeile in Zieldatei schreiben
>>"%ziel_datei%" echo\%zeile%  
GOTO :eof

:weiter
REM weitere Verarbeitung

cd /D %lag%BIN
start %lag%BIN\LAGER2HP.exe
echo warten auf LAGER2HP Ergebnis
ping 127.0.0.1 -n 5 > nul


REM Ergebnisse auslesen und in Datei schreiben

if %nr% EQU 1 type nul > %dat%Versch.txt


find "RAD. VERLAGERUNG IN X-RICHTUNG" %lag%work\LAGER2.AUS > temp.txt  
for /F "delims=GM  skip=2 tokens=4" %%a in (temp.txt) do @set zeile1=%%a  

find "RAD. VERLAGERUNG IN Y-RICHTUNG" %lag%work\LAGER2.AUS > temp.txt  
for /F "delims=GM  skip=2 tokens=4" %%b in (temp.txt) do @set zeile2=%%b  

find "AX. VERLAGERUNG IN Z-RICHTUNG" %lag%work\LAGER2.AUS > temp.txt  
for /F "delims=GM  skip=2 tokens=4" %%c in (temp.txt) do @set zeile3=%%c  
REM Werte in Ergebnisdatei schreiben
echo   %zeile1% %zeile2%%zeile3% >> H:\Lagerkram\Testlauf2\Dateien\Versch.txt

REM LAGER2.AUS umkopieren
copy %lag%work\lager2.aus %lag%work\Lager2%nr%.aus

set /a nr+=1
if %nr% leq %anzahl% goto :anfang

echo fertig

Womit nur hab ich das verdient? Ich nehme an, das es an Steuerzeichen ("%) liegt
Member: bastla
bastla Aug 12, 2010 at 23:20:20 (UTC)
Goto Top
Hallo Lowered!

Wenn in der "Lagerkraft.txt" die Zeilen weiterhin mit "L1", "L2", etc beginnen, wirst Du weiterhin auch das "L" in den Suchbegriff aufnehmen müssen - als Zeile 36 daher:
for /f "tokens=2-4 delims=;" %%a in ('findstr /b "L%quell_datei_nr%;" "%lager%"') do set "X=FRX = %%a" & echo %X% & set "Y=FRY = %%b" & set "Z=FAZ = %%c"
Da Du das Leerzeichen als "Delimiter" wieder entfernt hast, nehme ich an, dass Du die Schreibweise
<code type="plain>FRY = -0.04

der Variante
<code type="plain>FRY = -0.04

vorziehst ...
Die Zeilen 48 und 49 lassen sich übrigens wieder zusammenfassen (den Unterschied "FRX" zu "FAZ" hatte ich leider nicht berücksichtigt):
if defined zeile for %%a in (X Y Z) do echo %zeile%|findstr /b /r /c:"F[AR]%%a =">nul && (echo %%a & call set "zeile=%%%%a%%")
Den Rest habe ich mir nur oberflächlich angesehen; auf die jeweiligen "temp.txt" würde ich jedenfalls verzichten - etwa so:
for /F "skip=2 tokens=4 delims=GM" %%a in ('find "RAD. VERLAGERUNG IN X-RICHTUNG" "%lag%work\LAGER2.AUS"') do @set "zeile1=%%a"
wobei ich im Zweifelsfall zu "findstr" anstelle von "find" tendiere ...

Grüße
bastla
Member: Lowered
Lowered Aug 13, 2010 at 07:08:11 (UTC)
Goto Top
Hello,

also das L hatte ich bewusst entfernt, das ist nicht so wichtig.

Das es mehrere Zeilen für die Variablennamen FR und FA gibt ist auch ok, da kommen noch 2-3 ganz andere dazu.

Der obige Code hat prima funktioniert als ich die ganzen Pfade noch in den jeweiligen Zeilen hatte. Das habe ich dann versucht abzukürzen, indem ich die Pfade zu den einzelnen verzeichnissen (Daten, Programme) in eine Variable schreibe und überall da wo vorher der pfad stand nun %dat% oder %lag% schreibe.
Bisherige Erkenntnis ist, es steht und fällt mit der Datei Lagerkraft. Diese wird vermutlich beim set Befehl erkannt, kann aber danach nicht geöffnet werden wenn es um das auslesen geht.

Das kommt in der Lager2.ein Datei an:

$ Lagerbelastung 
DREHZAHL = 1800 



WBETA =  0.0 
WGAMMA = 0.0 
$ Ende 

d. h. in dem Bereich wo FRX, FRY und FAZ in die Datei kopiert werden sollen, läuft jetzt etwas falsch. Der Vergleich zwischen Quell und Zieldatei scheint noch zu funktionieren, sonst würde ja einfach weiter kopiert werden. Nur der Inhalt der Vergleichsvariablen kommt nicht in der Lager2.ein Datei an.

Das fehlende Leerzeichen bei den Delimitern ist Opfer meiner hochprofessionellen Fehlersuche geworden ;)

Grüße und vielen Dank.

Lowered
Member: bastla
bastla Aug 13, 2010 at 08:01:20 (UTC)
Goto Top
Hallo Lowered!
in dem Bereich wo FRX, FRY und FAZ in die Datei kopiert werden sollen, läuft jetzt etwas falsch.
Eher nicht; den Fehler würde ich, so wie Du das ohnehin schon angedeutet hattest, beim Auslesen aus der "Lagerkraft.txt" (also in Zeile 36) suchen - füge doch einfach einmal danach eine Zeile
echo %X%_%Y%_%Z% & pause
ein ...

Abgesehen davon kannst Du das "echo off" in der ersten Zeile während der Testphase in ein "echo on" änderrn und so dem Batch "beim Arbeiten zuschauen"; sinnvoll wäre es dazu auch, direkt von der Kommandozeile zu starten und vorweg über einen Klick links in der Titelleiste des CMD-Fensters die "Eigenschaften" und dort "Layout" aufzurufen und die Höhe der "Fensterpuffergröße" auf einen höheren Wert (ich verwende den Maximalwert 9999) zu setzen - so kannst Du entsprechend weit nach oben scrollen ...

Grüße
bastla
Member: Lowered
Lowered Aug 13, 2010 at 08:50:16 (UTC)
Goto Top
Hilfe zur Selbsthilfe ist eben doch die beste!

Problem gefunden und verstanden:

for /f "tokens=2-4 delims=;" %%a in ('findstr /b "%quell_datei_nr%;" "%lager%"') do set "X=FRX = %%a" & echo %X% & set "Y=FRY = %%b" & set "Z=FAZ = %%c"   

hat an der Stelle 'findstr /b "%quell_datei_nr% ein Problem mit der Lagerkraft.txt
dort steht vor den Nummern 1-9 Systembedingt ein Leerzeichen.
In der Ansysausgabe muss ich für Lagernummern größer 9 aber 2Speicherplätze reservieren. Also könnte ich im APDL eine Unterschiedung beim Speichern machen, für Nr <= 9 ein Speicherplatz, Nr > 9 2 Plätze.
Oder gibt es da im Batch-Script eine Möglichkeit ein ggf. erstes Leerzeichen zu Überspringen?
Wenn ich beim Aufruf ein Leerzeichen voranstelle ==>" %quell... werden nur noch die Zeilen mit Leerzeichen gelesen.

Was macht denn "°" ?
Member: bastla
bastla Aug 13, 2010 at 09:36:17 (UTC)
Goto Top
Hallo Lowered!

Wenn die Nummer immer 2 Zeichen umfasst (für Werte unter 10 eben ein Leerzeichen vorweg), ließe sich das so lösen:
set "quell_datei_nr= %quell_datei_n:~-1%"
set "quell_datei_nr=%quell_datei_nr:~-2%"
Hier wird zunächst vor die aus dem Dateinamen ausgelesene Nummer auf jeden Fall ein Leerzeichen gesetzt, dann aber das Ergebnis auf die letzten beiden Stellen beschränkt - dadurch kannst Du dann wieder ganz einfach nach %quell_datei_nr%" suchen ...
Was macht denn "°" ?
Falls Du damit "^" aus dem "findstr" meinen solltest - der Hilfe kannst Du entnehmen, dass dieses Zeichen alternativ zu "/b" dazu verwendet werden kann, für die Suche "Zeilenposition: Anfang der Zeile" vorzugeben - in der konkreten Anwendung hat es einfach den Sinn, jede Zeile zu suchen, die einen Zeilenanfang hat (und das sollten nun wirklich alle vorkommenden Zeilen sein face-wink; beim Zeilenende ist das nicht so sicher - Stichwort "Windows-Zeilenschaltung CR + LF") - also etwas kürzer formuliert: Damit werden alle Zeilen der Datei erfasst und mit "/n" nummeriert - Zweck der Übung ist es, Leerzeilen, die ansonsten in einer "for /f"-Schleife durch den Rost fallen, ebenfalls "mitzunehmen" ...

Grüße
bastla