18.6k Aufrufe
Gefragt in WindowsXP von romero Mitglied (323 Punkte)
hallöchen.

hab da folgenden sachverhalt.möchte eine ausgelesene (aus Excel) txt-datei mit folgendem inhalt (der inhalt der txt spielt keine große rolle):

a123-45678-000-00
a123-45679-001-00
...

dieser inhalt soll nun mit folgender FOR-schleife umbenannt und in eine neue txt gespeichert werden:

FOR /F "tokens=1,2,3 delims=-" %%a IN (test.txt) DO (
DIR C:\test\%%a_%%b_%%c >> test_neu.txt
)


ergebnis:

a123_45678_000
a123_45679_001
...

das klappt schon gut.

nun geht es aber weiter.nun steht aber,wenn er diese daten aus dem laufwerk zieht an der 15. stelle (gezählt wird ab der 1. stelle) ein buchstabe.je höher der buchstabe,desto aktueller ist die datei, sprich a < d < z < aa < ...

wenn ich aber mit der oben genannten "formel" das laufwerk auslese, bringt er mir alle dateien die bis zur 14. stelle so heißen.

er soll aber nur den aktuellsten nehmen,der der den höchsten buchstaben hat und diese in eine txt speichern.

hab schon versucht mit folgender formel das ganze zu machen, aber so richtig ist es noch nicht das was ich will.

FOR /F "tokens=1,2,3 delims=-" %%a IN (test.txt) DO DIR C:\test\ %%a_%%b_%%c FOR /L %%x IN (0,1,15) DO (
IF [%%x] EQU [14] IF [%%x] EQU [B] (
ECHO ok
)
)


also in worten ausgedrückt:

erst liest er die gezogene txt aus und sucht die entsprechende datei.dann soll er überprüfen (wenn er mehrere dateien mit dem selben namen (wie gesagt,bis zur 15. stelle gibt es mehrere dateien) findet),welche die aktuellste ist und diese dann in eine txt speichern.

so soll es aussehen:

gezogene txt:

a123-45678-000-00
a123-45679-001-00
...

umgewandelte txt:

a123_45678_000
a123_45679_000
...

gefundene dateien:

a123_45678_000A_20b.txt
a123_45678_000B_20b.txt
a123_45678_000D_20b.txt

a123_45679_001B_20b.txt
a123_45679_001H_20b.txt
a123_45679_001L_20b.txt
a123_45679_001W_20b.txt
a123_45679_001AA_20b.txt

...

endgültige bzw fertige txt:

a123_45678_000D_20b.txt
a123_45679_001AA_20b.txt
...

und das bekomm ich nicht hin.

hab zwar auch mit FINDSTR probiert aber da sucht er nur die raus die er mit dem entsprechendem buchstaben findet.also wenn er alle mit *B* findet,dann schreibt er diese raus,wenn er aber auch nach *C* suchen soll,dann nimmt er diese auch raus und da beißen sich dann 2 dateien,da nur die eine,die aktuellste gebraucht wird.

kann mir da einer helfen?vielen dank im voraus schonmal.

Romero

48 Antworten

0 Punkte
Beantwortet von son_quatsch Experte (5.3k Punkte)
Das besonders schwierige daran ist die von dir selbst aufgedrückte Sortierreihenfolge (nämlich AA nach Z statt nach A). Muss das unbedingt in .BAT sein?
0 Punkte
Beantwortet von romero Mitglied (323 Punkte)
ne nich in einer batch.kann auch von einem anderen script sein,so wie ein vb-srcipt.egal.aber das muss mit einem batch aufrufbar sein bzw mit windows funzen.

hat jemand da ne idee?
0 Punkte
Beantwortet von son_quatsch Experte (5.3k Punkte)
Ok, dann hier meine Lösung. Getestet mit WScript unter WinXP.
Testszenario:
[list]
[*] ich gehe davon aus, dass deine Liste schon entsprechend vorbereitet wurde, sodass mein Skript dann damit arbeiten kann
[*] Code als sn2260509.vbs abspeichern
[*] Datei angelegt: a123_45679_001A_1.txt (kein Inhalt)
[*] Datei angelegt: a123_45679_001Z_1.txt (kein Inhalt)
[*] Datei angelegt: a123_45679_001AB_1.txt (kein Inhalt)
[*] Datei angelegt: a123_45678_000D_1.txt (kein Inhalt)
[*] Datei angelegt: a123_45678_000A_2.txt (kein Inhalt)
[*] Datei angelegt: sn2260509in.txt (folgender Inhalt:)
a123_45678_000
a123_45679_001

[*] Eingabeaufforderung gestartet und ins Verzeichnis der Dateien gewechselt
[*] Aufruf:
sn2260509.vbs sn2260509in.txt sn2260509out.txt

[*] erzeugte Datei sn2260509out.txt enthielt wie erwartet:
a123_45678_000D_1.txt
a123_45679_001AB_1.txt

[/list]

Code des Skripts:

' Shellkommando ausführen (z.B. Notepad öffnen). Prüft auch gleich auf Fehler.
Function vExec( byVal sCmd )
On Error Resume Next
Set oExec = oShell.Exec(sCmd)

If Err.Number<> 0 Then
WScript.Echo "Quelle: " & Err.Source & vbCrLf & "Code: " & Err.Number & vbCrLf & "Text: " & Err.Description
WScript.Quit 255
End If
End Function

' Buchstabenfolge in Zahl umwandeln
Function iAsciiToInt( byVal sText )
Dim iMulti
iMulti = 1
iAsciiToInt = 0
While sText <> ""
iAsciiToInt = iAsciiToInt + Asc(Right(sText, 1)) * iMulti
sText = Left(sText, Len(sText)- 1)
iMulti = iMulti * 26
Wend
End Function


If WScript.Arguments.Count < 2 Then
WScript.Echo "Keine Parameter angegeben!" & vbCrLf & "Verwendung: SCRIPT IN.TXT OUT.TXT"
WScript.Quit 255
End If

Dim oExec, oShell, oFileSystem, oFileIn, oFileOut, sLine1, sLine2, sHighest, iHighest, oRe, aMatch, iValue
Set oShell = CreateObject("WScript.Shell")
Set oFileSystem = CreateObject("Scripting.fileSystemObject")
Set oRe = New RegExp
oRe.Pattern = "^.{14}([a-z]+)_.+\.txt"
oRe.IgnoreCase = True

Set oFileIn = oFileSystem.OpenTextFile(WScript.Arguments(0), 1)
Set oFileOut = oFileSystem.CreateTextFile(WScript.Arguments(1))
Do Until oFileIn.AtEndOfStream
sLine1 = oFileIn.ReadLine

vExec "cmd /c dir /b " & sLine1 & "*"
iHighest = 0
sHighest = ""
Do Until oExec.StdOut.AtEndOfStream
sLine2 = oExec.StdOut.ReadLine
Set aMatch = oRe.Execute(sLine2)
If aMatch.Count = 1 Then
iValue = iAsciiToInt(aMatch(0).SubMatches(0))
If iValue > iHighest Then
iHighest = iValue
sHighest = sLine2
End If
End If
Loop

If sHighest <> "" Then
oFileOut.WriteLine sHighest
Else
WScript.Echo "Nichts gefunden zu " & sLine1
End If
Loop
oFileIn.Close
oFileOut.Close
0 Punkte
Beantwortet von romero Mitglied (323 Punkte)
erstmal vielen vielen dank für diesen script.hab ihn auch gleich versucht zu testen.

so wie du es beschrieben hast.aber bei mir kommt immer das "nichts gefunden in ..." hoch.

bin im richtigen verzeichnis (also mit allen dateien die benötigt werden) und auch die eingabeaufforderung gestartet mit dem entsprechendem verzeichnis.

mach ich noch irgendwas falsch?

und noch ne frage.wenn aber die daten auf ein anderen laufwerk liegen,kann ich da irgendwie dem script sagen,suche erst in diesem laufwerk und dann auf dem anderen?also das er halt die zu suchende datei (als name in der input-datei.txt) erst auf einen laufwerk sucht,wenn er diese dann nicht findet,dann soll er auf das 2. laufwerk ausweichen.wo muss ich das in dem script eintragen?

und wenn der script-name ein anderer ist als die input- bzw die output-datei muss ich da diese zeile abändern? SCRIPT IN.TXT OUT.TXT

also z.b. die script-datei heißt "Liste_erstellen.vbs" (auf c:\), die input-datei "Liste_001_input.txt" (auf c:\),die output-datei "Liste_001.txt" (auf d:\)
0 Punkte
Beantwortet von romero Mitglied (323 Punkte)
kommando zurück er funktioniert.also diese passage meines vorherigen posts bitte überspringen!!!

*überglücklich ist*
0 Punkte
Beantwortet von son_quatsch Experte (5.3k Punkte)
Das mit "auf einem anderen Laufwerk" ist auch noch lösbar - das kann man im Batch selber ganz gut hinbekommen mit IF EXISTS.
Kannst dazu auch mal in der Kommandozeile folgendes aufrufen:
IF /?
0 Punkte
Beantwortet von romero Mitglied (323 Punkte)
ok werde das dann mal probieren.

aber da tut er doch nur das eine laufwerk durchsuchen oder?bzw erst das eine,schreibt alle gefundenen dann rein,die die er da nicht gefunden hat sucht er dann auf dem anderen laufwerk und hängt sie hinten an.aber er sollte da halt die eine ausgelesene auf dem einen laufwerk ausfindig machen,wenn da nicht,dann auf das andere.
geht das mit dem batch???also das mit dem IF EXISTS versteh ich da nicht?wie soll da die zeile aussehen?

also ruf sie ja mit der batch auf:

C:\Eigene Dateien\LISTE_ZIEHEN.vbs C:\Eigene Dateien\INPUT_DATEI.txt D:\output\OUTPUT_DATEI.txt

die daten liegen aber z.b. auf G:\dateien\
wie greift er denn darauf dann zu?

und was macht da diese zeile eigentlich ganz genau?

oRe.Pattern = "^.{14}([a-z]+)_.+\.txt"

da zieht er nur die erst gefundene datei oder?
0 Punkte
Beantwortet von son_quatsch Experte (5.3k Punkte)
Das mit "tut er doch" und "dann auf das andere" hab ich nicht verstanden. Vielleicht versuchst du das näher zu erläutern und am besten noch mit Beispielen - so wie in deinem ersten Posting.

C:\Eigene Dateien\LISTE_ZIEHEN.vbs C:\Eigene Dateien\INPUT_DATEI.txt D:\output\OUTPUT_DATEI.txt
Dieser Aufruf ist schon falsch, denn Leerzeichen sind Parametertrenner - du musst also alles (was Leerzeichen enthält) in doppelte Anführungsstriche setzen (kannst es aber sicherheitshalber auch tun, wenn kein Leerzeichen vorliegt):
"C:\Eigene Dateien\LISTE_ZIEHEN.vbs" "C:\Eigene Dateien\INPUT_DATEI.txt" "D:\output\OUTPUT_DATEI.txt"


oRe.Pattern = "^.{14}([a-z]+)_.+\.txt"
Das nennt sich regulärer Ausdruck und bewirkt später bei der Zeile
Set aMatch = oRe.Execute(sLine2)
dass nur Dateinamen gewählt werden die folgendem Muster entsprechen: beginnend mit 14 Zeichen, danach ein bis viele Buchstaben, danach ein Unterstrich, danach ein bis viele Zeichen, danach ein Punkt, danach "txt". Die runden (nicht die geschweiften) Klammern merken sich dann die Buchstabengruppe, nach der wir sortieren. Reguläre Ausdrücke sind eine komplexere Materie.
0 Punkte
Beantwortet von kicia Mitglied (939 Punkte)
Will nur mal anmerken:
Man kann ja auch vom Script aus die Existenz einer Datei feststellen.

Ich bin leider in vbs nicht so bewandert, ich bitte zu verzeihen, wenn mein Code unsauber ist.
(Arrays scheinen in vbs etwas schwierig zu sein, mit dem UBound und so, oder?)
Als Beispiel sollte es gehen:


MsgBox( checkIfExists( "test1.txt" ) )

Function checkIfExists( filename )
Dim arr(2), fso, i
Set fso = CreateObject("Scripting.fileSystemObject")
arr(0) = "c:/temp"
arr(1) = "h:/temp"

for i = 0 to 1
if( fso.FileExists( arr( i ) & "/" & filename ) ) Then checkIfExists = fso.GetFile( arr( i ) & "/" & filename )
next
End Function


(Ich empfehle übrigens jedem, der tiefer einsteigen will, JScript zu erwägen.)
0 Punkte
Beantwortet von romero Mitglied (323 Punkte)
an son_quatsch:

das mit dem in "" setzen wusste ich schon vom letzten vbs-script,aber danke nochmal für den hinweiß.

das mit dem "tut er doch" und "dann weiter" war so gemeint,das er erst z.b. auf "G:\daten" die 1. zu suchende datei da sucht,wenn er sie da nicht findet,dann soll er dann auf das laufwerk "F:\weitere_daten" zugreifen und da die datei suchen und speichern.kann man dann ne art fehlermeldung mit einbauen,also in diese txt-datei,das er die entsprechende nummer nicht gefunden hat???

ich weiß,das ich da vllt ein wenig viel verlange,aber vbs kenn ich mich gar nicht aus.deswegen wäre ich dir bzw euch sehr sehr dankbar.

und was ist wenn er aber z.b. 2 dateien finden, die wie folgt lauten:

a123_45678_002B_10a.txt
a123_45678_002B_10b.txt

oder weitere...

kann man die da auch mit einbauen?weil mein test hat es nicht wieder gegeben.also er nimmt da nur die erstgenannte datei.es wäre aber schön wenn er beide nehmen würde...

vielen vielen dank schonmal im vorraus


oRe.Pattern = "^.{14}([a-z]+)_.+\.txt"

würde für 2 buchstaben hintereinander auch das gehen?
oRe.Pattern = "^.{14}([a-z]+[a-z])_.+\.txt"
...