uhu-stic
Goto Top

Text-Datei mittels Batchprogramm konvertieren - Zeilen löschen, ungültige Einträge löschen, variable Länge in fixe Länge, Duplikate löschen

Hallo zusammen,
erst mal vielen Dank für diese Webseite - ich habe hier viel gelernt und auch meine Anforderung gelöst bekommen!
Nun stehe ich vor dem Problem, dass die Batch die ich erstellt habe, zwar funktioniert, jedoch alles andere als performant ist und entsprechend lange zur Verarbeitung braucht.
Leider muss ich auf ein Batchprogramm zurückgreifen - somit keine gutgemeinten Ratschläge bzgl. VBS o.ä.

back-to-topBeschreibung der Aufgabe

Ich habe die Herausforderung eine Datei von Format A nach Format B zu wandeln und den ein oder anderen "Fehler" aus dieser zu entfernen.
Konkret bedeute dies:

  1. Die Datei beginnt mit fünf Zeilen - die nicht weiter benötigt werden und gelöscht (bzw. nicht in die Ergebnissdatei geschrieben) werden können
  2. Die Datei hat sowohl " als auch Leerstellen die sich bei der weiteren Verarbeitung als "störend" herausstellten, somit habe ich diese " eliminert und die Leerstellen gegen ~ (Tilde) ersetzt - dies ist jedoch nur ein Zwischenschritt, auf den ich gerne verzichten würde
  3. Die Datei hat nach den ersten zwei Schritten fehlerhafte Einträge, die ich gerne loswerden würde. Fehlerhafte Einträge können sein
    1. Eine Nummer (Jobnummer) in der Datei ist nicht gleich dem Dateinamen (die Jobnummer sind die ersten 9 Stellen der ReferenceNumber)
    2. Der weitere Teil der ReferenceNumber (Stücknummer = letzte 7 Stellen der ReferenceNumber) in der Datei wurde fehlerhaft übergeben und an der letzten Stelle fehlt die Zahl
    3. Die ReferenceNumber wurde gar nicht übergeben
      • All diese drei fehlerhaften Einträge sollen in eine Errorlog geschrieben werden
  4. Die nun "bereinigte" Datei soll von der variablen Länge in eine fixe Länge gebracht werden, nicht alles was in der Ursprungsdatei steht, wird in der Zieldatei gebraucht. Außerdem werden Einträge teilweise verändert bzw. die Positionen neu gemischt.
  5. Die Zieldatei muss sortiert ausgegeben werden
  6. Die Zieldatei darf keine doppelten Einträge haben. Dieser Teil ist im Moment der, der mir am meisten weh tut - er dauert einfach ewig.
    1. Mit Batchdatei aus einer .txt alle doppelten Zeilen (Duplikate) komplett löschen
      • Variante 1 von bastla vom 27.05.2009 um 21:29:07 habe ich verstanden und so nachgebaut.
      • Variante 4 von LotPings vom 28.05.2009 um 11:01:26 Uhr hingegen kapiere ich überhaupt nicht. Dort scheint aber ein Sort direkt mit in die Abfrage eingebaut zu sein - evtl. macht es dies effizienter?
        • Ich hatte hier die Idee, dass man die hier momentan implementierte FINDSTR Abfrage irgendwie so abändert, dass diese, aufgrund der Tatsache, dass die Datei ja bereits sortiert ist, immer nur die n nächsten Zeilen prüft und wenn in LineNo+=1 keine Übereinstimmung gefunden wird, die Prüfung abgebrochen wird. Nach meinem Verständnis geht der FINDSTR Befehl immer die komplette Datei durch, bei meiner momentanen Testdatei mit ca. 7500 Einträgen dauert das doch recht lange face-sad
  7. So, zum Schluss will ich noch den Statuswert von X nach Y umsetzen - hätte ich vermutlich schon weiter oben mitmachen können... Somit bitte nicht meckern - die von mir erstellte Batch ist meine erste etwas größere, die Anfängerfehler seien mir also bitte verziehen.

Hier mal ein Schnipsel aus der Datei - damit geht es natürlich flott und alles ist fein - wie gesagt, meine Testdatei ist leider 7500 Einträge groß, die in der Realität können auch mal 60000 Einträge haben...

back-to-topTestdatei mit allen relevanten "Fehlern"

123456789.txt
Firstline to be deleted
Second line to be deleted
Third line to be deleted
Forth line to be deleted
"RecordTime" "ReferenceNumber" "NotNeeded1" "NotNeeded2" "NotNeeded3" "NotNeeded4" "NotNeeded5" "NotNeeded6" "NotNeeded7" "NotNeeded8" "NotNeeded9" "NotNeeded10" "Status" "NotNeeded11" "NotNeeded12" "Cnt01" "Cnt02" "NotNeeded12" "NotNeeded13" "NotNeeded14" "NotNeeded15" "NotNeeded16" "NotNeeded17"  
"2012.12.12.15.54.04" "" 1 1 1 1 1 0 1 0 0 0 2 0 8 2 0 0 0 0 0 0 0  
"2012.12.12.15.54.07" "123456789000000" 1 1 0 1 1 600 1 1 0 1 1 0 24 5 0 0 0 0 0 0 0  
"2012.12.12.15.54.08" "1234567890000000" 1 1 0 0 1 200 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0  
"2012.12.12.15.54.09" "1234567890000000" 1 1 0 0 1 200 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0  
"2012.12.12.15.54.10" "1234567890000000" 1 1 0 0 1 200 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0  
"2012.12.12.16.29.03" "1234567890000066" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.29.05" "1234567890000067" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.32.38" "123456789000006" 1 1 0 1 1 500 1 1 0 1 1 0 144 3 1 0 0 0 0 0 0  
"2012.12.12.16.32.50" "1234567890000069" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.33.44" "1234567890000070" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.35.45" "1234567890000107" 1 1 0 1 1 400 1 1 0 1 1 0 8 2 1 0 0 0 0 0 0  
"2012.12.12.16.37.30" "1234567890000108" 1 0 0 1 1 400 1 1 0 1 1 0 10 2 1 0 0 0 0 0 0  
"2012.12.12.16.37.31" "1234567890000109" 0 1 0 1 1 400 1 1 0 1 1 0 9 2 1 0 0 0 0 0 0  
"2012.12.12.16.40.46" "1234567890000111" 1 1 0 1 1 400 1 1 0 1 0 0 136 1 2 0 0 0 0 0 0  
"2012.12.12.16.42.27" "1234567890000111" 1 1 1 1 1 0 1 0 0 0 2 0 136 1 0 0 0 0 0 0 0  
"2012.12.12.16.43.32" "1234567890000114" 1 1 0 1 1 600 1 1 0 1 1 0 152 2 3 0 0 0 0 0 0  
"2012.12.12.16.43.33" "1234567890000115" 1 1 0 1 1 500 1 1 0 1 1 0 8 3 1 0 0 0 0 0 0  
"2012.12.12.16.43.34" "1234567890000116" 1 1 0 1 1 400 1 1 0 1 1 0 8 2 1 0 0 0 0 0 0  
"2012.12.12.16.43.35" "1234567890000117" 1 1 0 0 1 500 1 0 0 0 0 0 0 3 1 0 0 0 0 0 0  
"2012.12.12.16.51.47" "1234567890000155" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.57.28" "1234567890000156" 1 1 0 0 1 500 1 0 0 0 0 0 0 3 1 0 0 0 0 0 0  
"2012.12.12.16.57.29" "1234567890000157" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.57.30" "1234567890000158" 0 0 0 1 1 200 1 1 0 1 1 0 27 1 0 0 0 0 0 0 0  
"2012.12.12.16.57.31" "1234567890000158" 0 1 0 1 1 300 1 1 0 1 1 0 17 1 1 0 0 0 0 0 0  
"2012.12.12.16.57.32" "1234567890000159" 1 1 0 1 1 500 1 1 0 1 1 0 16 3 1 0 0 0 0 0 0  
"2012.12.12.16.57.34" "1234567890000160" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.57.35" "1234567890000161" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.16.57.36" "1234567890000162" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.18.48.41" "1234567890000798" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.18.53.59" "1234567890000798" 1 1 1 1 1 0 1 0 0 0 2 0 136 2 0 0 0 0 0 0 0  
"2012.12.12.18.55.05" "100000800220000" 1 1 0 1 1 500 1 1 0 1 1 0 152 3 1 0 0 0 0 0 0  
"2012.12.12.18.55.10" "1234567890000802" 1 1 0 1 1 800 1 1 0 1 1 0 136 2 5 0 0 0 0 0 0  
"2012.12.12.18.55.10" "1234567890000803" 1 1 0 0 1 500 1 0 0 0 0 0 0 3 1 0 0 0 0 0 0  
"2012.12.12.18.55.10" "1234567890000804" 1 1 0 0 1 400 1 0 0 0 0 0 0 2 1 0 0 0 0 0 0  
"2012.12.12.19.19.24" "1234567890002889" 1 1 0 1 1 400 1 1 0 1 1 0 136 3 0 0 0 0 0 0 0  
"2012.12.12.19.19.26" "1234567890002890" 1 0 0 1 1 400 1 1 0 1 1 0 10 2 1 0 0 0 0 0 0  
"2012.12.12.19.40.36" "" 1 1 1 1 1 0 1 0 0 0 2 0 8 0 0 0 0 0 0 0 0  
"2012.12.12.19.40.42" "" 1 0 1 1 1 0 1 0 0 0 2 0 26 1 0 0 0 0 0 0 0  
"2012.12.12.19.40.51" "123456789000289" 0 1 1 1 1 0 1 0 0 0 2 0 153 3 2 0 0 0 0 0 0  
"2012.12.12.19.40.52" "1234567890002896" 1 1 0 1 1 400 1 1 0 1 1 0 128 3 0 0 0 0 0 0 0  
"2012.12.12.19.40.54" "1234567890002897" 1 1 0 1 1 300 1 1 0 1 1 0 128 2 0 0 0 0 0 0 0  
"2012.12.12.19.35.50" "1234567890005231" 1 1 0 1 1 800 1 1 0 1 1 0 152 2 5 0 0 0 0 0 0  



back-to-topMeine Batchdatei

Hier dann also mein Code - wie in meinem Vorwort geschrieben, 99% von dem ist von dieser Seite abgeleitet, somit wundert Euch nicht, dass man die Handschrift des Einen oder Anderen von Euch in dem Skrpit wiederfindet:

 
@echo off 
setlocal enabledelayedexpansion 

set "Datei=C:\Test\%1"   
set "JobID=%1"  
set "t=%temp%\Temp.tmp"   
if exist "%t%" del "%t%"   

::----Hier werden die Schritte 1. (fünf Zeilen üerbspringen) und 2. (" rausschmeißen, Leerzeichen gegen Tilde ersetzen) durchgeführt 
set "Von= "  
set "Nach=~"  
FOR /F "delims=" %%i in ("%Datei%") do (   
       FOR /F "usebackq skip=5 delims=" %%j in ("%%~i") do set "line=%%j" & set "line=!line:%Von%=%Nach%!" & echo !line:^"=!>>"%t%"  
)
move "%t%" "%Datei%"  

::----Hier wird Schritt 3.1. (Jobnummer ungleich Dateiname rausschmeißen) durchgeführt
::----Es wird eine Error Datei mit den fehlerhaften Einträgen erzeugt 
for /f "usebackq delims=" %%i in ('%Datei%') do set "JobID=%%~ni"   
for /f "tokens=1-4 delims=:," %%a in ("%time%") do set "Stunde=%%a" & set "Minute=%%b" & set "Sekunde=%%c" & set "Milisekunde=%%d"   
for /f "usebackq delims=" %%i in ("%Datei%") do call :ProcessLine0 "%%i"   
move "%t%" "%Datei%"  

::----Hier wird Schritt 3.2. (Stücknummer zu kurz, durch das ersetzen in 2. steht hier nun immer eine ~) durchgeführt
(die letzte Stelle fehlt)
set "CodeA=~"   
for /f "usebackq delims=" %%i in ("%Datei%") do call :ProcessLine1 "%%i"   
move "%t%" "%Datei%"  

::----Hier wird Schritt 3.3. (Stücknummer ungültig - es steht immer eine 0000000 da) durchgeführt
set "CodeB=0000000"   
for /f "usebackq delims=" %%i in ("%Datei%") do call :ProcessLine2 "%%i"   
move "%t%" "%Datei%"  

::----Hier wird Schritt 4. (Variable Länge wird auf fixe Länge geändert, Felder werden neu angeordnet) durchgeführt
set "Leer16=                     "  
set "Leer20=                         "  
set "Leer3=000"  

for /f "tokens=1-23 delims=~" %%a in (C:\Test\%1) do (    
    set "RecordTime=%%a%Leer20%"   
    set "ReferenceNumber=%%b%Leer16%"   
    set "Status=%Leer3%%%m"  
    set "Cnt01=%Leer3%%%p"  
    set "Cnt02=%Leer3%%%q"  
    set /a "Cnt1=%%p"  
    set /a "Cnt2=%%q"  
    set /a "CntTotal=CntAim1+CntAim2"  
echo !ReferenceNumber:~0,16! !Status:~-2! !RecordTime:~0,4!!RecordTime:~5,2!!RecordTime:~8,2!!RecordTime:~11,2!!RecordTime:~14,2!!RecordTime:~17,2! !Cnt01:~-3! !Cnt02:~-3! !CntTotal!>>"%t%"  
)  
move "%t%" "%Datei%"  

for /f "tokens=1-6 delims= " %%a in (C:\Test\%1) do (    
    set "ReferenceNumber=%%a"  
    set "Status=%%b"  
    set "RecordTime=%%c"  
    set "Cnt01=%%d"  
    set "Cnt02=%%e"  
    set "CntTotal=%Leer3%%%f"  
echo !ReferenceNumber! !Status! !RecordTime! !Cnt01! !Cnt02! !CntTotal:~-3! 98>>"%t%"  
)  
move "%t%" "%Datei%"  

::----Hier wird Schritt 5. (die Datei wird aufsteigend sortiert) durchgeführt
sort "%Datei%">"%t%"  
move "%t%" "%Datei%"  

::----Hier wird Schritt 6. (die doppelten Einträge werden aus der Datei gelöscht) durchgeführt
set "Duplikate=%temp%\Duplikate.txt"  
set /a LineNo=0 
copy nul "%Duplikate%">nul  
for /f "usebackq delims=" %%i in ("%Datei%") do set "Zeile=%%i" & call :ProcessLine3  
move "%t%" "%Datei%"  
del "%Duplikate%"  

::----Hier wird Schritt 7. (Statuswert wird verändert) durchgeführt - gute werden von 00 auf 10 gesetzt alle anderen (schlechten) auf 20
set "Status=00"   
for /f "usebackq delims=" %%i in ("%Datei%") do (  
    set "Z=%%i" & call :ProcessLine4   
)
move "%t%" "%Datei%"  


::----Unterhalb dieser Zeile werden die Processlines abgearbeitet - das goto :eof ist somit für alle darüber liegenden Abfragen 
goto :eof 

:ProcessLine0 
set "Line=%~1"   
if "%Line:~20,9%"=="%JobID%" echo !Line!>>"%t%"  
if not "%Line:~20,9%"=="%JobID%" echo !Line!>>"%JobID%"_%date%_!Stunde!!Minute!!Sekunde!.err  
goto :eof

:ProcessLine1 
set "Line=%~1"   
if not "%Line:~35,1%"=="%CodeA%" echo !Line!>>"%t%"  
goto :eof

:ProcessLine2 
set "Line=%~1"   
if not "%Line:~29,7%"=="%CodeB%" echo !Line!>>"%t%"  
goto :eof

:ProcessLine3
set /a LineNo+=1 
rem echo Prüfe Zeile %LineNo% ... 
findstr /b /c:"%Zeile:~0,16%%D%" "%t%">nul && >>"%Duplikate%" echo %Zeile% || >>"%t%" echo %Zeile%  
goto :eof

:ProcessLine4 
set "Line=%Z:~0,50%%D%"  
set "ReferenceNumber=%Z:~0,16%%D%"  
set "HintererTeil=%Z:~20,30%%D%"  
if not "%Line:~17,2%"=="%Status%" echo !ReferenceNumber! 20 !HintererTeil!>>"%t%"  
if "%Line:~17,2%"=="%Status%" echo !ReferenceNumber! 10 !HintererTeil!>>"%t%"  
goto :eof

So, nun habe ich nicht mehr viel hinzuzufügen. Außer, dass Euch mein Dank sicher ist!
Eine letzte Anmerkung / Fragen hätte ich jedoch noch:
Bei den Tests bin ich einmal von einer drehenden Platte auf eine SSD umgezogen, da ich vermutete, dass die schlechte Performance primär in den Schreib- und Lesevorgängen begründet ist. Eine echte Verbesserung konnte ich jedoch nicht feststellen. Somit noch die Frage, wie kann ich meine Batchdatei evtl. mit mehr CPU Power schneller machen?
Ein Aufruf von start /high namederbatch.bat 123456789.txt hat leider nichts gebracht.

Content-Key: 196895

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

Ausgedruckt am: 28.03.2024 um 20:03 Uhr

Mitglied: Friemler
Friemler 13.01.2013, aktualisiert am 14.01.2013 um 12:19:18 Uhr
Goto Top
Hallo UHU-stic,

ich habe einige Optimierungen eingebaut und ein paar Protokoll-Ausgaben eingefügt. Hier ist das Ergebnis:
@echo off & setlocal enabledelayedexpansion

set "Datei=%~1"  
set "JobID=%~n1"  
set "t=%TEMP%\Temp.tmp"  


::----Hier werden die Schritte 1. (fünf Zeilen üerbspringen) und 2. (" rausschmeißen, Leerzeichen gegen Tilde ersetzen) durchgeführt 
echo Schritte 1 u. 2

set "Von= "  
set "Nach=~"  

(for /f "usebackq skip=5 tokens=* delims=" %%j in ("%Datei%") do (  
   set "line=%%j"  
   set "line=!line:%Von%=%Nach%!"  
   echo !line:^"=!  
)) >"%t%"  

move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 3.1. (Jobnummer ungleich Dateiname rausschmeißen) durchgeführt
::----Es wird eine Error Datei mit den fehlerhaften Einträgen erzeugt
echo Schritt 3.1

for /f "tokens=1-4 delims=:," %%a in ("%TIME%") do (  
  set "Stunde=%%a"  
  set "Minute=%%b"  
  set "Sekunde=%%c"  
  set "Milisekunde=%%d"  
)

(for /f "usebackq tokens=* delims=" %%i in ("%Datei%") do (  
   set "Line=%%i"  
   if "!Line:~20,9!" equ "%JobID%" (  
     echo !Line!
   ) else (
     1>&2 echo !Line!
   )
)) 1>"%t%" 2>"%JobID%_%DATE%_%Stunde%%Minute%%Sekunde%.err"  

move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 3.2. (Stücknummer zu kurz, durch das ersetzen in 2. steht hier nun immer eine ~) durchgeführt
::(die letzte Stelle fehlt)
echo Schritt 3.2

set "CodeA=~"  

(for /f "usebackq tokens=* delims=" %%i in ("%Datei%") do (  
   set "Line=%%i"  
   if "!Line:~35,1!" neq "%CodeA%" echo !Line!  
)) >"%t%"  

move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 3.3. (Stücknummer ungültig - es steht immer eine 0000000 da) durchgeführt
echo Schritt 3.3

set "CodeB=0000000"  

(for /f "usebackq tokens=* delims=" %%i in ("%Datei%") do (  
   set "Line=%%i"  
   if "!Line:~29,7!" neq "%CodeB%" echo !Line!  
)) >"%t%"  

move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 4. (Variable Länge wird auf fixe Länge geändert, Felder werden neu angeordnet) durchgeführt
echo Schritt 4

set "Leer16=                     "  
set "Leer20=                         "  
set "Leer3=000"  

(for /f "usebackq tokens=1,2,13,16,17 delims=~" %%a in ("%Datei%") do (  
   set "RecordTime=%%a%Leer20%"  
   set "ReferenceNumber=%%b%Leer16%"  
   set "Status=%Leer3%%%c"  
   set "Cnt01=%Leer3%%%d"  
   set "Cnt02=%Leer3%%%e"  
   set /a Cnt1=%%d
   set /a Cnt2=%%e
   set /a CntTotal=CntAim1+CntAim2
   echo !ReferenceNumber:~0,16! !Status:~-2! !RecordTime:~0,4!!RecordTime:~5,2!!RecordTime:~8,2!!RecordTime:~11,2!!RecordTime:~14,2!!RecordTime:~17,2! !Cnt01:~-3! !Cnt02:~-3! !CntTotal!
)) >"%t%"  

move "%t%" "%Datei%" > NUL  

(for /f "usebackq tokens=1-6" %%a in ("%Datei%") do (  
   set "CntTotal=%Leer3%%%f"  
   echo %%a %%b %%c %%d %%e !CntTotal:~-3! 98
)) >"%t%"  

move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 5. (die Datei wird aufsteigend sortiert) durchgeführt
echo Schritt 5

sort "%Datei%" > "%t%"  
move "%t%" "%Datei%" > NUL  


::----Hier wird Schritt 6. (die doppelten Einträge werden aus der Datei gelöscht) durchgeführt
echo Schritt 6

set "Duplikate=%TEMP%\Duplikate.txt"  
set /a Cnt=0
set "Line="  
set "PrevLine="  

type NUL > "%Duplikate%"  

(for /f "usebackq tokens=* delims=" %%a in ("%Datei%") do (  
   set "Line=%%a"  
   
   if /i "!Line:~0,16!" equ "!PrevLine:~0,16!" (  
     echo %%a
     set /a Cnt+=1
   )
   set "PrevLine=%%a"  
)) >"%Duplikate%"  

if %Cnt% gtr 0 (
  findstr /v /g:"%Duplikate%" "%Datei%" > "%t%" && (  
    move "%t%" "%Datei%" > NUL  
  )
)

del "%Duplikate%" >NUL 2>&1  


::----Hier wird Schritt 7. (Statuswert wird verändert) durchgeführt - gute werden von 00 auf 10 gesetzt alle anderen (schlechten) auf 20
echo Schritt 7

set "Status=00"  

(for /f "usebackq tokens=* delims=" %%i in ("%Datei%") do (  
   set "Z=%%i"  
   set "Line=!Z:~0,50!"  
   set "ReferenceNumber=!Z:~0,16!"  
   set "HintererTeil=!Z:~20,30!"  

   if "!Line:~17,2!" equ "%Status%" (  
     echo !ReferenceNumber! 10 !HintererTeil!
   ) else (
     echo !ReferenceNumber! 20 !HintererTeil!
   )
)) >"%t%"  

move "%t%" "%Datei%" > NUL  

Ich habe den Doppelte-Zeilen-Finden-Algorithmus gewählt, den @77559 seinerzeit in dem von Dir schon gefundenen Thread veröffentlicht hat.

Als weitere Optimierungen habe ich sämtliche Unterprogramme beseitigt und bei allen FOR-Schleifen die Ausgabeumleitung aus dem Schleifenrumpf herausgeholt und auf die komplette Schleife gelegt. Dadurch muss die Ausgabedatei nur einmal zum Schreiben geöffnet werden. Das zusammen bringt sehr viel Performancegewinn.

Ich habe außerdem den Rat von @jeb-the-batcher befolgt und den Kopf aller FOR-Schleifen, wo ein "delims=" stand, auf "tokens=* delims=" geändert.

Ob das Ergebnis Deinen Anforderungen entspricht kannst am besten Du selbst beurteilen. Ich poste hier mal die Ausgabedateien.

Die 123456789.txt
1234567890000066 10 20121212162903 002 001 000 98
1234567890000067 10 20121212162905 002 001 000 98
1234567890000069 10 20121212163250 002 001 000 98
1234567890000070 10 20121212163344 002 001 000 98
1234567890000107 20 20121212163545 002 001 000 98
1234567890000108 20 20121212163730 002 001 000 98
1234567890000109 20 20121212163731 002 001 000 98
1234567890000111 20 20121212164046 001 002 000 98
1234567890000114 20 20121212164332 002 003 000 98
1234567890000115 20 20121212164333 003 001 000 98
1234567890000116 20 20121212164334 002 001 000 98
1234567890000117 10 20121212164335 003 001 000 98
1234567890000155 10 20121212165147 002 001 000 98
1234567890000156 10 20121212165728 003 001 000 98
1234567890000157 10 20121212165729 002 001 000 98
1234567890000158 20 20121212165730 001 000 000 98
1234567890000159 20 20121212165732 003 001 000 98
1234567890000160 10 20121212165734 002 001 000 98
1234567890000161 10 20121212165735 002 001 000 98
1234567890000162 10 20121212165736 002 001 000 98
1234567890000798 10 20121212184841 002 001 000 98
1234567890000802 20 20121212185510 002 005 000 98
1234567890000803 10 20121212185510 003 001 000 98
1234567890000804 10 20121212185510 002 001 000 98
1234567890002889 20 20121212191924 003 000 000 98
1234567890002890 20 20121212191926 002 001 000 98
1234567890002896 20 20121212194052 003 000 000 98
1234567890002897 20 20121212194054 002 000 000 98
1234567890005231 20 20121212193550 002 005 000 98

Die 123456789_13.01.2013_225939.err:
2012.12.12.15.54.04~~1~1~1~1~1~0~1~0~0~0~2~0~8~2~0~0~0~0~0~0~0
2012.12.12.18.55.05~100000800220000~1~1~0~1~1~500~1~1~0~1~1~0~152~3~1~0~0~0~0~0~0
2012.12.12.19.40.36~~1~1~1~1~1~0~1~0~0~0~2~0~8~0~0~0~0~0~0~0~0
2012.12.12.19.40.42~~1~0~1~1~1~0~1~0~0~0~2~0~26~1~0~0~0~0~0~0~0

Gruß
Friemler
Mitglied: UHU-stic
UHU-stic 14.01.2013 um 09:39:02 Uhr
Goto Top
Mein lieber Herr Gesangsverein,

das nenne ich mal 'ne Performancesteigerung! Ich war so stolz, als ich durch eine Änderung in der Dublettenprüfung die Prozesszeit von 30 auf 15 MINUTEN reduziert hatte.
Die Steigerung durch das Script von Friemler ging von ~15 MINUTEN auf 4,5 SEKUNDEN !!!

Was soll ich sagen - DANKE!

Viele Grüße und weiter so

UHU-stic
Mitglied: Friemler
Friemler 14.01.2013 um 09:54:06 Uhr
Goto Top
Moin UHU-stic,

danke für die Blumen. face-smile

Ich habe mir heute Morgen mit frischem Kopf noch mal Gedanken zu der Dublettenprüfung gemacht. Wie mir scheint, tauchen doppelt vorkommende Zeilen in der Ausgabedatei garnicht mehr auf. Einmal sollten sie aber wohl auftauchen.

Melde Dich mal, ob das so ist, dann kann ich da noch nacharbeiten.

Gruß
Friemler
Mitglied: UHU-stic
UHU-stic 14.01.2013 aktualisiert um 10:34:49 Uhr
Goto Top
Moin Friemler,

also wenn ich das richtig sehe, dann sind die doppelten Einträge weiterhin drin - siehe Deine Ausgabedatei Zeile 8 & 9 bzw. 17 & 18.

Wenn Du da noch mal einen Blick riskieren würdest? Ich werde es parallel auch noch mal tun.

Merci

UHU-stic
Mitglied: Friemler
Friemler 14.01.2013 um 11:29:32 Uhr
Goto Top
Hallo UHU-stic,

ja, der Fehler war zwar genau anders herum, als ich dachte, aber ich hatte doch irgendwie das Gefühl, das an der Stelle noch was faul ist.

Anyway, ich habe das Script oben jetzt geändert und nochmal getestet, sollte funktionieren.

Gruß
Friemler
Mitglied: UHU-stic
UHU-stic 14.01.2013 um 13:43:02 Uhr
Goto Top
Mahlzeit Friemler,

na wenn das mal keine prompte Behandlung ist - und es denkt einer mit, somit nochmals: Vielen Dank!

Nun habe ich, durch den kleinen Duplettenfehler in Deinem Skript von gestern Nacht, nochmals alle Dupletten geprüft und dabei eine Besonderheit in meiner Testdatei bemerkt, die ich bis dato noch nicht gesehen hatte:
Eine Duplette hat teilweise einen inkonsitenten Status. Will meinen, dass Sie im Feld Status einmal den Status 0 (gut) und dann im nächsten Eintrag den Status ungleich 0 hat.
Ich habe dieses Szenario nun mal in Zeile 18 & 19 meiner Testdatei am Beispiel der Stücknummer 111 eingebaut.
Bei meiner ursprünglichen Duplettenabfrage schien immer der letzte (untere - nach dem Sort in Schritt 5) Eintrag in die Ergebnisdatei zu laufen - was dazu führte, dass es mir bis dato gar nicht aufgefallen war, nun läuft scheinbar der erste (oberste) Eintrag in die Ergebisdatei.

Somit wäre die "Logik" dass eine Duplette immer als ungültig gemeldet sein muss.
Ich würde da ja nun irgendwie in Schritt 6 ansetzen, in der Du mit Deiner Variable PrevLine ja momentan (weil bis dato so auch richtig) die 16 Stellen der ReferenceNumber abfragst. Man müsste nun, vermute ich, irgendwie noch das Statusfeld mit abfragen.

Wie kann man das nach Deiner Meinung am besten lösen?

Gruß - UHU-stic
Mitglied: UHU-stic
UHU-stic 14.01.2013 aktualisiert um 14:15:46 Uhr
Goto Top
Hallo Friemler, nochmal ich,

Habe nun die Zeile 123 aus Deinem Skript
echo %%a
gegen
echo !PrevLine!
getauscht und es behebt mein Problem / Fehler.
Birgt das Deiner Meinung nach andere Risiken? Ich habe bis dato immer nur zwei Einträge pro Stücknummer gesehen, jedoch befürchte ich, dass auch hier noch ungeantes Fehlerprotential schlummert...
Was wäre also wenn dort mehr als zwei Einträge stünden?
Mitglied: Friemler
Friemler 14.01.2013 aktualisiert um 19:54:33 Uhr
Goto Top
Hallo UHU-stic,

das wollte ich gerade fragen:

  • Sind das immer maximal 2 Zeilen oder können es auch mehr sein?
  • Ist es immer so, dass, wenn eine der Zeilen in der Status-Spalte einen Wert ungleich 00 hat, diese Zeile als zweites bzw. nach den Zeilen mit einem Wert gleich 00 kommt?

Du könntest ja die Zeile 123 durch
echo !PrevLine!&echo %%a
ersetzen und das Löschen der Duplikate.txt deaktivieren. Dann lass das Script über eine wirklich große Realworld-Eingabedatei laufen, die an die 60000 Einträge herankommt. Danach könntest Du mit einem neuen Batchfile, in das Du den Codeabschnitt der Dublettenerkennung hineinkopierst und etwas anpasst, die Duplikate.txt auf doppelte Zeilen untersuchen. Dabei prüfst Du dann aber nicht nur die ersten 16 Zeichen einer Zeile, sondern komplette Zeilen. Wenn Du dabei Dubletten findest, ist der Fall aufgetreten, dass es mehr als zwei Zeilen mit der gleichen ReferenceNumber gibt.

Btr. Deine Frage "Was passiert wenn es mehr als 2 Zeilen mit der gleichen ReferenceNumber gibt":
Das sollte kein Problem sein. Die Schleife vergleicht ja immer die aktuelle und die vorhergehende Zeile miteinander. Bei Gleichheit wird (nach Deiner Änderung) die Vorgängerzeile in die Duplikate.txt geschrieben. Der spätere Aufruf von FINDSTR sorgt dann dafür, dass alle Zeilen, die in der Duplikate.txt stehen, in der Ausgabedatei nicht mehr auftauchen. Somit würde von den Zeilen mit gleicher ReferenceNumber die als letztes in der Eingabedatei stehende in der Ausgabedatei auftauchen. Deshalb auch meine zweite Frage oben.

Gruß
Friemler