Jump to content

Zwei Dateien vergleichen und das Resultat in eine dritte speichern


Der letzte Beitrag zu diesem Thema ist mehr als 180 Tage alt. Bitte erstelle einen neuen Beitrag zu Deiner Anfrage!

Empfohlene Beiträge

Hallo Leute,

 

da ich vorher nie etwas mit Auswertung zu tun hatte, wende ich mich an Euch.

Ich habe zwei Dateien die ich miteinander vergleichen will und das Resultat in eine neue Datei schreiben möchte.

 

Datei 1 sieht so aus:

3499

6542

3211

9878

3439

5468

...

 

Datei 2 dagegen so:

Markus;Mustermann;mmann;3499

Warkus;Musterfrau;wmuster;3439

Markuw;Schuster;masdchr;5468

...

 

Nun möchte ich aus der Datei 1 die erste Zeile nehmen und in der Datei 2 danach suchen.

Wird diese Zahl gefunden, soll der dritte string und die Zahl in die Datei 3 geschrieben werden. Und das mit der kompletten Datei.

Wird kein passender String gefunden, soll einfach noid geschrieben werden.

Beispiel:

 

Datei 3:

 

3499;mmann

6542;noid

 

Has jemand eine Idee wie man es am besten löst kann?

Evtl. gibt es dafür Tools? Vielleicht kennt jemand ja ein Paar Beispielskripte in WSH?

 

Danke!

Link zu diesem Kommentar

Eine Idee:

In MS Access die zwei Dateien einbinden oder verknüpfen.

Dann ne Abfrage in der eine Verknüpfung zwischen Feld1 aus Datei1 und Feld4 aus Datei2 hergestellt wird mit der Verknüpfungseigenschaft "Alle aus Datei1 und nur die aus Datei2..."

Auszugebende Felder dann Feld1 von Datei1 und Feld3 von Datei2

Wenn die Abfrage dann hübsche DAten liefert, über "Extras - Office-Verknüfungen" im passenden Format ausgeben.

Link zu diesem Kommentar

Hier mal ein Besipiel. Ohne Fehlerroutinen etc.

Die Dateinamen könnte man ggf. auch noch komfortabel als Übergabeparameter gestalten..

Wenns bei langen Listen zu lange läuft, muß man sich noch was anderes überlegen.

 

strFileInID = "C:\IDs.txt"
strFileIn = "C:\Liste.txt"
strFileOut = "C:\Ausgabe.csv"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set txtInID = objFSO.OpenTextFile(strFileInID, 1)
Set txtIn = objFSO.OpenTextFile(strFileIn, 1)
Set txtOut = objFSO.CreateTextFile(strFileOut)

Do While txtInID.AtEndOfStream = False
flgfound = false
   	strInID = txtInID.ReadLine
Set txtIn = objFSO.OpenTextFile(strFileIn, 1)
Do While txtIn.AtEndOfStream = False
   		strIn = txtIn.ReadLine
	strColumns = split(strIn,";")
	if strInID = strColumns(3) then
		strZeile = strInID & ";" & strColumns(2)
		flgfound = true
		Exit Do
	end if
Loop
txtIn.Close
if not(flgfound) then strZeile = strInID & ";noid"
txtOut.WriteLine strZeile 
Loop
MsgBox "Fertig"

Link zu diesem Kommentar

Moin m43stro,

 

alternativ kannst Du solche Dönekens auch mit einer Zeile direkt vom CMD-Prompt abfackeln... da lohnt es sich ja nicht, einen Batch zu schreiben...


(=20:23:54 D:\temp=)
>for /f %i in (datei1.txt) do @for /f "delims=; tokens=3" %j in ('findstr "%i" datei2.txt') do @echo %i;%j
3499;mmann
3439;wmuster
5468;masdchr
[/Code]

Falls das so passt, kannst du noch ein ">>datei3.txt" dahintersetzen.

 

P.S. Besser im Auge behalten kannst Du solche Oneliner, wenn Du vorher eingibst.

[Code]
mode con cols=166 lines=55
[/Code]

 

 

[Edit] sorry, ich hatte den Teil mit der "NoId" überlesen.

Wenn das noch rein soll, dann wird es natürlich eine ganze Zeile.

[Code]
(=20:39:25 D:\temp=)
>for /f %i in (datei1.txt) do @for /f "delims=; tokens=3" %j in ('findstr "%i" datei2.txt^|^|echo %i^;noid^>con') do @echo %i;%j
3499;mmann
6542;noid
3211;noid
9878;noid
3439;wmuster
5468;masdchr
4711;noid
[/Code]

Grüße

Biber

Link zu diesem Kommentar

@Cybquest

Danke für das Resultat.

Hat auf Anhieb funktioniert, allerdings hat es ein Manko.

Die ID's kommen manchmal doppelt vor, das wird nicht berücksichtigt.

Das habe ich auch nur durch Bibers-Lösung erfahren.

Diese berücksichtigt es schon.

Habe versucht in den Schleifen Exit Do rauszunehmen oder statt while until zu verwenden, aber er prüft nur solange bis er eine findet und führt mit der nächsten Zeile fort.

Vorteil an VBS ist, es ist ein Paar Sekunden schneller.

Die Datei 2 beinhaltet schon knapp 2000 Datensätze.

 

@Biber

Von Deiner Lösung war ich verblüfft, was doch mit cmd alles möglich ist.

Warum klappt es nicht, wenn ich es in einer *.bat speichere?

Ist es keine Bat-Programmierung?

 

Allerdings finde ich diese Programmierung sehr komplex.

Also ich sehe da einfach keine Logik.

Was bedeuten diese ganzen Zeichen:

^|^|echo %i^;noid^>con

Vor allem sehe ich nicht wo die id rausgeholt wird.

Kennst Du eine gute Seite für diese Programmierung, damit ich es richtig verstehen und später selber anwenden kann?

 

Danke

Link zu diesem Kommentar

Moin M43stro,

 

vorweg: natürlich würde ich auch in der Praxis so einen quick-and-dirty-Oneliner vom CMD-Prompt nur als Proof-of-Concept verwenden.

Wenn es denn in Ansätzen klappt, dann lässt es sich auch als Batch halbwegs lesbar formatiert abbilden.

Einer der Hauptunterschiede zwischen Batch-Ausführung und Abfeuern vom CMD-Prompt aus ist, dass die Zählvariablen (die %i und %j der FOR-Anweisungen in einer Batchdatei mit zwei Prozentzeichen geschrieben werden, also als %%i und %%j usw.

 

Ich versuche mal diese Zeile aufzudröseln, empfehle aber ausdrücklich eine lesbare/wartbare Variante wir z.B. den Schnipsel von Cybquest.

 

==[1]=> for /f %i in (datei1.txt) do ...

Für alle Zeilen in Datei1.txt tue...

 

==[2]=> @for /f "delims=; tokens=3" %j in ('findstr "%i" datei2.txt^|^|echo %i^;noid^>con') do

Für alles, was von der inneren Klammer als Ausgabe produziert wird, nimm das 3.Token, wenn jede Zeile als Delimiter Semikolons hat.("tokens= 2 delims=;")

 

==>[2 innere Klammer]=> 'findstr "%i" datei2.txt^|^|echo %i^;noid^>con'

Das ist ein bisschen kryptisch - aber nicht blenden lassen...

Da sind 2 Fälle berücksichtigt, nämliche der "Gefunden"-Fall und der "Nix-gefunden-Fall"

a) Gefunden-Fall: dann liefert "FindStr "%i" datei2.txt" (%i ist eine ID-Zeile aus datei1.txt) die Fundzeile aus Datei2.txt

Beispiel:


Findstr "3439" datei2.txt
Warkus;Musterfrau;wmuster;3439
[/Code]

--> Von "Warkus;Musterfrau;wmuster;3439" getrennt nach ";" das dritte Token ist "wmuster" .

--> dann steht also in Variablen %i der Wert 3439 und in %j der Wert "wmuster".

--> ein @echo %i;%j ergibt in diesem Fall @echo 3439;wmuster

b) Nicht-gefunden-Fall:

dann einfach nur das %i, den Suchwert ECHOen und noid dahinter. Das steht hier:

^|^|echo %i^;noid^>con'

 

Normalerweise wäre dieser Befehl direkt am CMD-Prompt ja nur "@echo %i;moid".

Da dieser aber innerhalb einer neuen CMD-Instanz ausgeführt werden soll UND auch nur, wenn findstr nichts liefert, muss ich schreiben:

 

"gib mir die Fundzeile(n) von FindStr zurück ODER den @cho-noid-String".

--> Findstr "4711" datei2.txt ODER das echo-noid

-->FindStr "4711" datei2.txt||@echo 4711;noid

Die Vorzeile würde genau so vom CMD-Prompt funktionieren.

Da ich diese an eine andere CMD-Instanz als Parameter übergeben will, maskiere ich alle Steuerzeichen mit einem Caret "^"

-->FindStr "4711" datei2^|^|@echo 4711^;noid

Auch das Semikolon, weil ich genau das dummerweiser im anderen Kontext als "Delims" definiert habe.

Und ich leite die Ausgabe explizit auf die Konsole um (mit ">con"). Und muss auch da das Steuerzeichen ">" maskieren. Also ^> schreiben.

 

 

==>[3]=> @echo %i;%j

...gibt die Variablen %i und %j aus.

 

Nochmal in einem Stück:

[1] for /f %i in (datei1.txt) do ...

[2] @for /f "delims=; tokens=3" %j in (

--[2a] 'findstr "%i" datei2.txt

-- ODER ^|^|

--[2b] echo %i^;noid^>con

[3] ') do @echo %i;%j

 

Empfehlungen zum Einlesen (ohne Scherz): die Hilfen am CMD-Prompt.

Insbesondere cmd /?, For /?.

Exotische oder etwas abgedrehte Batch-Schnipsel sind auch einige auf IT-Forum, Tutorials, News und Knowledgebase - administrator zu finden.

 

Grüße

Biber

Link zu diesem Kommentar

@Biber: Wow... bin auch beeindruckt, was man auf der Commandozeile alles machen kann! Hut ab!

 

@m43stro:

Nur das Exit Do rausnehmen reicht nicht!

Einfach das exit Do durch die Ausgabe ersetzen

Unten dann die Ausgabe rausnehmen und den noid-Fall etwas umbiegen:

Do While txtInID.AtEndOfStream = False
flgfound = false
   	strInID = txtInID.ReadLine
Set txtIn = objFSO.OpenTextFile(strFileIn, 1)
Do While txtIn.AtEndOfStream = False
   		strIn = txtIn.ReadLine
	strColumns = split(strIn,";")
	if strInID = strColumns(3) then
		strZeile = strInID & ";" & strColumns(2)
		flgfound = true
                                txtOut.WriteLine strZeile 
	end if
Loop
txtIn.Close
if not(flgfound) then txtOut.WriteLine strInID & ";noid"
Loop

Link zu diesem Kommentar

@Biber

vielen Dank für die Erklärung aus erster Hand.

Besonders für die detaillierte Erklärung des kryptischen Teils.

Werde ist mal in eine Bat-Form bringen und bin schon auf die neuen Aufgaben gespannt.

Das erleichtert die Arbeit sehr, wenn mal erstmal weiß wie es geht.

 

@Cybquest

Danke auch Dir für die Ergänzung.

werde mir den Threa bookmarken

 

Euch ein schönes Wochenende

Link zu diesem Kommentar

Moin m43stro,

 

weil ich gerade gesehen habe, dass der Beitrag immer noch offen ist und ich weiß, dass Du an einer Batchlösung feilst... es geht auch viel übersichtlicher.

 

Der FindStr-Befehl kennt u.a. auch einen Parameter "/G:Textdatei-mit-Suchworten".

Wenn Du die Datei1.txt als derartige Datei-mit-Suchworten verwendest und in zwei Duchlaufen einmal nach den Zeilen mit Treffern und einmal nach den Suchworten ohne Treffern suchst, dann ergibt sich folgender schlanker 4-Zeiler.

 


@echo off & if exist %temp%\tmpfile del %temp%\tmpfile
for /f "delims=; tokens=3,4" %i in ('findstr /G:datei1.txt datei2.txt') do @echo %j;%i >>%temp%\tmpfile
for /f %i in ('findstr /V /G:datei1.txt datei2.txt') do @echo %i;noid>>%temp%\tmpfile
Sort %temp%\tmpfile > dateiFinal.txt
[/Code]

 

Das halte ich für einen wartbaren Batch.

 

Grüße

Biber

Link zu diesem Kommentar

Noch ein Nachtrag, sorry.

 

habe gestern Bullshit gepostet - lag bestimmt an dieser Hessen-Wahl...*grmpff*

 

Also - Streiche den Schnipsel von gestern.

Setze.

 


@echo off & if exist %temp%\tmpfile del %temp%\tmpfile
for /f "delims=; tokens=3,4" %%i in ('findstr /G:datei1.txt datei2.txt') do @echo %%j;%%i >>%temp%\tmpfile
for /f %%i in (datei1.txt) do findstr "%%i" datei2.txt>nul || @echo %%i;noid>>%temp%\tmpfile
Sort %temp%\tmpfile > dateiFinal.txt
[/Code]

 

Zum einen fehlten die doppelten statt einfachen Prozentzeichen, zum anderen funktioniert die "FindStr /V" ("Suche alle nicht vorhandenen")-Variante nicht.

 

Aber so sollte es passen.

 

Grüße

Biber

Link zu diesem Kommentar

@Biber

Habe deine letzte Version nun studiert und bin wirklich begeistert.

Mit Hilfe von Batch-Programmierung - Wikibooks konnte ich nun alles nachvollziehen.

 

Weiterhin dachte ich über eine Eingabemöglichkeit nach.

Mit choice kann man dem Benutzer diverse Optionen zur Verfügung stellen.

Stimmt es, dass man mit Windowseigenen Mitteln keine Abfrage mit Batch machen kann?

Z.B. in dem Skript oben würde ich gerne die Dateinamen abfragen.

 

Danke

Link zu diesem Kommentar

Moin m43stro,

 

Abfragen kannst Du durchaus im Batch machen - oder Parameter direkt mit übergeben oder eine Kombination aus beidem (Setzen von Defaultwerten)

 

Das interaktive Abfragen funktioniert mit dem Befehl Set /P (siehe Set /? am CMD-Prompt).

 

Beispiel:

Set /P INdatei=Bitte Inputdateinamen angeben:

-oder besser-

...
:FragNachINdatei
Set /P "INdatei=Bitte Inputdateinamen angeben: "
:: Einen Default kannst Du entsprechend setzen z.b. eine Zeile danach...
IF "%InDatei%" == "" set "inDatei=c:\daten\Kundendatei.txt"
If not exist "%InDatei%" (
echo Datei %indatei% nicht vorhanden, bitte neu eingeben!
goto :FragNachINdatei
)
...
[/Code]

 

Grüße

Biber

Link zu diesem Kommentar
Der letzte Beitrag zu diesem Thema ist mehr als 180 Tage alt. Bitte erstelle einen neuen Beitrag zu Deiner Anfrage!

Schreibe einen Kommentar

Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor-Fenster leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...