windowsuser1984
Goto Top

Newbe need help for-schleife

habe die windows hilfe schon duchgeblättert aber komme zu keinem Ziel

Hi @ all

sry das ich so bekloppten sachen frage aber quäle mich schon seit ner weile damit rum und mir fehlen einfach die kenntnise, vernünftige beispiele finde ich leider auch nicht ...

Probelmbeschreibung:
möchte gerne erste spalte einer textdatei(D1),Zeichen sind durch leerzeichen getrennt, mit einer anderen textdatei(D2) vergleichen,
wenn nun der Zeichensatz aus der ersten spalte(D1) in der 1. spalte(D2) nicht vorkommt in die (D2) schreiben notfalls auch erst in eine tmp und später in die (D2)

mein Ansatz war volgender:

for /F "tokens=1,2*" %%i in ("%1") do (
if "%%FOUND%%"==0 echo %%LINE%% >> datei.tmp
set FOUND=1
set FIND=%%i
set LINE=%%i %%j
for /F "tokens=1,2*" %%i in (%DATEI%) do (
if "%%FIND%%"=="%%i" set FOUND=1
))

weiteres Problem:

Funktion - möchte aus einer datei 3 Parameter auslesen aber einige sind nicht vergeben und sollen übersprungen werden.
wieder ein ansatz von mir

set COUNT=1
for /F "tokens=1,2,3*" %%i in (%1) do (
if "TEXT1"=="%%i" do set STRING%%COUNT%%=%%k
)
if not "%STRING1%"=="" SET /a COUNT=%COUNT%+1
for /F "tokens=1,2,3*" %%i in (%1) do (
if "TEXT2"=="%%i" do set STRING%%COUNT%%=%%k
)
if not "%STRING2%"=="" SET /a COUNT=%COUNT%+1

aber jetzt beim tippen fällt mir auf was sein könnte - wenn die erste schleife nichts findet bleibt STRING1 leer und die 2. schleife schreibt in STRING1 (bis hirher is es genau so gewollt)
aber dann wird nicht weiter hochgezählt, da in der letzten zeile geprüft wird ob STRING2 leer ist.
aber wie kann ich das lösen, kann ja nicht schreiben
if not "%STRING%COUNT%%"==""

bitte um hilfe
und bei gelegenheit einige for-schleifen als beispiele mit variablen mit erklärung wär echt super
thx

Content-Key: 42436

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

Ausgedruckt am: 28.03.2024 um 11:03 Uhr

Mitglied: miniversum
miniversum 18.10.2006 um 15:49:00 Uhr
Goto Top
Hilfe zum Forbefehl findest du wenn du in der Eingabeaufforderung for /? eingibst.

zum ersten Problem:

Spalten vergleichen geht nicht, wenn dann Zeilen.
Wenn Du das willst dann:
Soll immer nur die erste Zeile von D1 mit der ersten zile von D2 verglichen werden? Oder ob die erste Zeile von D1 irgentwo in D2 vorkommt?

miniversum
Mitglied: bastla
bastla 18.10.2006 um 15:54:04 Uhr
Goto Top
Hallo WindowsUser1984!

Dein Problem 1 verstehe ich wie folgt:
Du hast zwei Textdateien, in denen jeweils in den einzelnen Zeilen mindestens 2 durch Leerzeichen und/oder Tabulatoren getrennte Werte stehen, wobei der erste dieser Werte als "Schlüssel" dient.
Als Ergebnis möchtest Du, dass alle Zeilen der ersten Datei, deren Schlüsselwert sich noch nicht in den Schlüsselwerten der zweiten Tabelle befindet, an die zweite Tabelle angehängt werden. Richtig?

Problem 2 ist für mich "problematischer", da die eigentliche Zielsetzung nicht zu erkennen ist. Vielleicht könntest Du mit einigen Beispielen (Zeilen der Eingabedatei und gewünschtes Ergebnis) den Sinn der Aktion deutlich machen!
Mitglied: bastla
bastla 18.10.2006 um 16:40:08 Uhr
Goto Top
Hallo WindowsUser1984!

Auf Verdacht ein Entwurf für Problem 1:

@echo off
for /f "tokens=1*" %%i in (TestDat.txt) do call :Vergl %%i "%%j"  
set neu=
goto :eof
:Vergl
set neu=1
for /f "tokens=1*" %%a in (VerglDat.txt) do call :Vergl2 %1 %%a  
if %neu%==1 echo %1 %~2 >> VerglDat.txt
goto :eof
:Vergl2
if /i %1==%2 set neu=0

Alle Zeilen von TestDat.txt werden darauf hin untersucht, ob der erste Wert (bis zum ersten Leerzeichen/Tab) bereits in einer Zeile von VerglDat.txt als erster Wert vorkommt (Groß- / Kleinschreibung wird nicht unterschieden). Wenn dem nicht so ist, wird die ganze Zeile aus TestDat.txt (oder genauer, der erste Wert, eine Leerstelle und der Rest der Zeile) an VerglDat.txt angehängt. Hinweis: Falls das Trennzeichen in TestDat.txt ein Tab war, wird trotzdem als neues Trennzeichen eine Leerstelle verwendet.

Natürlich lässt sich das Ganze so ändern, dass die beiden Dateinamen als Argumente übergeben werden können - liest sich dann nur etwas schwerer als die obige Variante. face-wink


Für das Problem mit der Übernahme der "Originalzeile" (also ohne ev. verändertes Trennzeichen bzw mit enthaltenen Anführungszeichen) ist mir noch folgendes eingefallen:

for /f "delims=" %%i in (TestDat.txt) do set line=%%i & call :Vergl  
set neu=
goto :eof
:Vergl
set neu=1
for /f "tokens=1*" %%a in (VerglDat.txt) do call :Vergl2 %%a %line%  
if %neu%==1 echo %line% >> VerglDat.txt
goto :eof
:Vergl2
if /i %1==%2 set neu=0

Hier nehme ich die ganze Zeile in einer Variable mit und lasse das Herausfiltern des ersten Wertes durch die automatische Aufspaltung bei der Übergabe an :Vergl2 erledigen ...

Grüße
bastla
Mitglied: bastla
bastla 18.10.2006 um 17:16:49 Uhr
Goto Top
Und weil ich gerade dabei bin - eine Alternative zu obigem Ansatz:

@echo off
for /f "tokens=1*" %%i in (TestDat.txt) do findstr /b /i %%i VerglDat.txt || echo %%i %%j >> VerglDat.txt  

Ich nehme an (ohne es getestet zu haben), dass diese Version bei größeren Dateien erhebliche Laufzeitvorteile bringen müsste.

bastla

[Edit] %%~j auf %%j reduziert [/Edit]
Mitglied: WindowsUser1984
WindowsUser1984 19.10.2006 um 02:15:52 Uhr
Goto Top
vielen dank
eine schnelle lösung, nichts anderes von dir gewohnt - thx a lot
probiere es gleich morgen aus

Zu meinem 2. Prob nochmal.
Habe mir ne kleine bat gebaut die ua eine datei(lokal) auf die anderen 2 PCs im Netzwerk und server an eine bestimmte Stelle kopiert.
Weiter soll an einem anderen Rechner(4) nur an die anderen 3 rechner schicken.
Diese Datei möchte ich nun von allen PCs aus starten und nicht 4 verschiedene versionen davon machen (recht umständlich bei anderungen an der datei...)
Von dem otherPC(4) aus möchte ich aber nicht an den server senden.
Daten werden an otherPC(4) vorbereitet und dan den PC1 - PC3 korregiert/bearbeitet und auf die die anderen PCs und den server gesichert ... heufigkeit ca 10 - 25 mal täglich
(bin ja so schlecht beim erklären - malen wär fast einfacher ^^)

also habe ich eine lokale Datei mit den netzwerkadressen der anderen PC die ich auslese.
Da ich in dieser Datei ua weitere Parameter für andere Dateien habe kann ich auch nicht einfach die ersten 3 Zeilen auslesen da ich für meine anderen batches dann wiederum an dem Problem hänge.

z.B.:
Datei von PC2:

PC1 = \\blabla1...
PC3 = \\blabla3...
server = \\AAAA...

Datei von otherPC

PC1 = \\....
PC2 = \\....
PC3 = \\....
server = \\....

nun ist die lösung gesucht zum auslesen dieser lokalen dateien mit adressen der pcs, so das ich von allen PCs nur eine funktionierende version brauche
Mitglied: bastla
bastla 19.10.2006 um 08:37:09 Uhr
Goto Top
Hallo WindowsUser1984!

Daten werden an otherPC(4) vorbereitet und dan den PC1 - PC3 korregiert/bearbeitet und auf die die anderen PCs und den server gesichert ... heufigkeit ca 10 - 25 mal täglich

Von dem otherPC(4) aus möchte ich aber nicht an den server senden.

also habe ich eine lokale Datei mit den netzwerkadressen der anderen PC die ich auslese.

z.B.:
Datei von PC2:

> PC1 = \\blabla1...
> PC3 = \\blabla3...
> server = \\AAAA...

Datei von otherPC

> PC1 = \\....
> PC2 = \\....
> PC3 = \\....
> server = \\....

An sich unterscheidet sich für mich die Situation (programmtechnisch) zwischen den Rechnern 1 bis 3 und dem Rechner 4 nicht wirklich - alle haben eine lokal gespeicherte Liste von Zielrechnern (in der Liste kommt - sinnvoller Weise - der eigene Rechner nicht vor, bei Rechner 4 sollte eben zusätzlich auch der Server nicht drinnen sein), an die dann per Batch kopiert wird.

Da ich in dieser Datei ua weitere Parameter für andere Dateien habe kann ich auch nicht einfach die ersten 3 Zeilen auslesen da ich für meine anderen batches dann wiederum an dem Problem hänge.

Müssen die weiteren Parameter (bitte auch dazu Beispiele) wirklich in der gleichen Datei stehen?

nun ist die lösung gesucht zum auslesen dieser lokalen dateien mit adressen der pcs, so das ich von allen PCs nur eine funktionierende version brauche

Sinnvolle Überlegung - allerdings würde ich aber, wie oben angedeutet, die Rechnerliste getrennt von weiteren Einstellungen führen.

Grüße
bastla
Mitglied: Metzger-MCP
Metzger-MCP 19.10.2006 um 09:33:59 Uhr
Goto Top
.
Mitglied: WindowsUser1984
WindowsUser1984 19.10.2006 um 11:10:51 Uhr
Goto Top
hm
Die adresse für den server benötige ich zB auch für den 4. Rechner
und pfad für den einen Programmordner sollte in der lokalen Parameter Datei stehen,
pfad für logdateien.
Also alles was sich nur unter den einzelnen PCs unterscheidet
noch ein beispiel:
\AA\BBB\CCCC\LOG
Wie gesagt möchte nicht immer 4 verschiedene versionen der batchs schreiben.

ja wenns nicht anders geht dann mach ich die rechnerliste extra
oder mir fällt doch noch eine andere lösung ein ....

swie würden den nun deine lösung aussehen wenn die rechnerliste so abändere das nur die zielpfade der einzelnen rechner vorkommen?
meine kopierdatei sieht momenatan ungefähr(stark verkürzt) so aus:

(auslesen der ZIELPFADE)
if not exist %ZIELPATH1% echo Pfad nicht vorhanden oder netzwerk nicht verbunden & pause
if not exist %ZIELPATH2% echo Pfad nicht vorhanden oder netzwerk nicht verbunden & pause
if not exist %ZIELPATH3% echo Pfad nicht vorhanden oder netzwerk nicht verbunden & pause
xcopy %~1 %ZIELPATH1% /C /E /I
xcopy %~1 %ZIELPATH1% /C /E /I
xcopy %~1 %ZIELPATH1% /C /E /I
if nor exist %ZIELPATH1%%~nx1 echo datei %~n1 konnte nicht kopiert werden
if nor exist %ZIELPATH2%%~nx1 echo datei %~n1 konnte nicht kopiert werden
if nor exist %ZIELPATH3%%~nx1 echo datei %~n1 konnte nicht kopiert werden
pause

danke nochmal für deine Zeit und nerven und gedult
Mitglied: bastla
bastla 19.10.2006 um 15:37:07 Uhr
Goto Top
Hallo WindowsUser1984!

Vielleicht ziehst Du das Ganze wie folgt auf:

Lokale Rechnerliste(n) mit zeilenweisem Eintrag der Zielrechner und -Pfade:
C:\Listen\Alle.txt und C:\Listen\AlleWS.txt (letztere ohne Server)

Beispiel für den Inhalt von Alle.txt auf PC2 (\\Rechnername\Freigabe\Unterverzeichnis[se]):
\\blabla1\Import\Neue
\\blabla3\Import3\Neu\Ganz Neu
\\AAAA\Eingang\Gesamt

Batch-Datei am Server: Verteil.cmd in Freigabe Batches

Die Batchdatei würde dann nach Deiner Vorgabe so aussehen:
@echo off
for /f "delims=" %%i in (%2) do Call :Kopiere %1 "%%i"  
goto :eof
:Kopiere
if not exist %2 echo %2 nicht vorhanden oder Netzwerk nicht verbunden. & pause
xcopy %1 %2 /C /E /I 2>nul >nul
if not exist "%~2\%~nx1" echo Datei %~n1 konnte nicht kopiert werden. & echo.  

Aufruf daher von jedem Rechner (zB zum Kopieren von "QuellDat.txt" aus "D:\Zu Verteilen" auf alle Zielrechner):
\\Server\Batches\Verteil.cmd "D:\Zu Verteilen\QuellDat.txt" C:\Listen\Alle.txt (oder AlleWS.txt)  

Noch eine Frage: Werden eigentlich mehrere Dateien gleichzeitig kopiert (was /E vermuten ließe)? In diesem Fall wäre die Überprüfungsabfrage (für %~nx1) etwas problematisch ...

Grüße
bastla
Mitglied: WindowsUser1984
WindowsUser1984 20.10.2006 um 01:42:49 Uhr
Goto Top
Hi
habe noch ein paar fragen ...
"delims=" in der hilfe steht, Zeichen das das std Trennzeichen(leer und tab) ersetzt
da aber keines angegeben ist frage ich mich warum es überhaubt da steht?
und nehme an wenn die tokens nicht vorkommen wird alles gelesen und als %1 weitergegeben?
call :kopiere %1 "%%i" (wuste nicht das goto nicht geht aber dafür call)
sieht so aus als springst du aus der schleife und wieder zurück!
wie wird festgelegt wann in der for-schleife weitergemacht wird?
funktioniert das auch mit einem befehl oder muss die Datei dort enden?
Nehme an das %1 "%%i" als %1 %2 weitergegeben werden!?
Bin mir nicht sicher aber goto :eof dient zum beenden des programmablaufes durch undefinierter Sprungmarke!?

ansonsten denke ich das ichs verstanden habe
achja das /E ist nur ausversehen da reingeraten aber danke fürs mitdenken, villt kommt das dann in einer späteren version noch zum einsatz aber bisher nur einzelne Files

mal schauen ob ichs hinbekomme
hätte natürlich alles blind übernehmen können aber denke wenn ichs mal verstehe dann belästige ich dich weniger ;-D
thx again a lot
Mitglied: bastla
bastla 20.10.2006 um 08:56:01 Uhr
Goto Top
Hallo WindowsUser1984!

"delims=" in der hilfe steht, Zeichen das das std Trennzeichen(leer und tab) ersetzt da aber keines angegeben ist frage ich mich warum es überhaubt da steht? und nehme an wenn die tokens nicht vorkommen wird alles gelesen und als %1 weitergegeben?

So ist es - Ziel ist, die ganze Zeile aus der Rechnerliste zu lesen (erspart mir, in der Datei Alle.txt Anführungszeichen zu verwenden, diese wegzufiltern und wieder neu zu setzen)

call :kopiere %1 "%%i" (wuste nicht das goto nicht geht aber dafür call) sieht so aus als springst du aus der schleife und wieder zurück!

Ja (nennt sich Unterprogrammtechnik)
wie wird festgelegt wann in der for-schleife weitergemacht wird? funktioniert das auch mit einem befehl oder muss die Datei dort enden?
Letzteres

Nehme an das %1 "%%i" als %1 %2 weitergegeben werden!?
Wie beim Aufruf der Batchdatei selbst sind alle übergebenen Argumente durchnummeriert

Bin mir nicht sicher aber goto :eof dient zum beenden des programmablaufes durch undefinierter Sprungmarke!?
Richtig

hätte natürlich alles blind übernehmen können aber denke wenn ichs mal verstehe dann belästige ich dich weniger ;-D
Find ich gut face-smile, betrachte Deine Fragen aber keineswegs als Belästigung, sondern eher als Herausforderung

Grüße
bastla
Mitglied: WindowsUser1984
WindowsUser1984 20.10.2006 um 12:58:39 Uhr
Goto Top
also das nach dem call die datei enden muss ist schon etwas dämlich aber jetzt weis ichs wenigstens

danke nochmal jetzt bekomme ich es villt sogar selbst hin
mal gucken

bis irgendwann dann wiede ;-D
Mitglied: Biber
Biber 20.10.2006 um 15:00:28 Uhr
Goto Top
Moin WindowsUser1984,
ich glaube (so wie ich den Thread mitgelesen habe), dass ihr an einer Stelle aneinander vorbeigeschrieben habt:

wie wird festgelegt wann in der for-schleife weitergemacht wird?
funktioniert das auch mit einem befehl oder muss die Datei dort enden?
Letzteres.

Mitnichten.
Die *.bat-Datei muss dort nicht enden.
In einer *.bat/*.cmd-Datei können auch mehrere "call :subBlock"-Aufrufe stehen.

Jeder dieser Blöcke sollte eigentlich mit einem "goto :eof" enden.
In diesem Kontext ("geCALLter Anweisungsblock") bedeutet "goto :eof" in etwa dasselbe wie in anderen Skript-Sprachen "RETURN" oder "END PROC"..also Ende der aufgerufenen Unterroutine.

Das "sollte eigentlich" eben heißt: Wenn ein Call-Anweisungsblock-Ende zufällig gleichzeitig auch das Ende der Batchdatei ist (so wie in bastla's Skizze), dann kann/darf das abschließende "goto :eof" entfallen.

Nicht entfallen dagegen darf das "goto :eof", das das Ende des "Haupt-Batches" angibt - das nach der FOR..IN..DO-Anweisung.

@WindowsUser1984
Bitte den Beitrag auf "Gelöst" setzen, wenn es für Dich auch hinreichend beantwortet ist. Danke.

@bastla
Es sollte nur eine Klarstellung einer IMHO missverständlichen Formulierung sein.
Habe sonst keinerlei Einwände gegen die Lösungsskizze.

Gruß
Biber
Mitglied: bastla
bastla 20.10.2006 um 15:54:03 Uhr
Goto Top
@Biber

Danke für die Ergänzung/Klarstellung - hatte beim Beantworten etwas wenig Zeit ...

Grüße
bastla
Mitglied: WindowsUser1984
WindowsUser1984 20.10.2006 um 23:13:06 Uhr
Goto Top
danke für diesen nachtrag, beseitigt natürlich das missverständniss
gut aufgepasst

oh - hätte ich jetzt vergessen, jetzt ist er auf gelöst

thx