m43stro 10 Geschrieben 24. Januar 2008 Melden Teilen Geschrieben 24. Januar 2008 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! Zitieren Link zu diesem Kommentar
Cybquest 36 Geschrieben 24. Januar 2008 Melden Teilen Geschrieben 24. Januar 2008 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. Zitieren Link zu diesem Kommentar
m43stro 10 Geschrieben 24. Januar 2008 Autor Melden Teilen Geschrieben 24. Januar 2008 Würde gerne auf Software, die extra kostet verzichtet. Ich wollte das eher als Skript realisieren, damit ich es überall mitnehmen kann. Zitieren Link zu diesem Kommentar
Cybquest 36 Geschrieben 24. Januar 2008 Melden Teilen Geschrieben 24. Januar 2008 Wie groß sind denn die Dateien so? Gehts da eher um ein paar, ein paar hundert oder gar um ein paar Tausend Zeilen? Wenns wirklich viele sind, muss man beim scripten schon ein bissle aufpassen, das Ganze optimiert laufen zu lassen, damit's nicht ewig dauert... Ich such mal, was ich im Fundus hab. Zitieren Link zu diesem Kommentar
Cybquest 36 Geschrieben 24. Januar 2008 Melden Teilen Geschrieben 24. Januar 2008 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" Zitieren Link zu diesem Kommentar
Biber 10 Geschrieben 24. Januar 2008 Melden Teilen Geschrieben 24. Januar 2008 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;%j3499;mmann3439;wmuster5468;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;%j3499;mmann6542;noid3211;noid9878;noid3439;wmuster5468;masdchr4711;noid[/Code] Grüße Biber Zitieren Link zu diesem Kommentar
m43stro 10 Geschrieben 25. Januar 2008 Autor Melden Teilen Geschrieben 25. Januar 2008 @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 Zitieren Link zu diesem Kommentar
Biber 10 Geschrieben 25. Januar 2008 Melden Teilen Geschrieben 25. Januar 2008 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 Zitieren Link zu diesem Kommentar
Cybquest 36 Geschrieben 25. Januar 2008 Melden Teilen Geschrieben 25. Januar 2008 @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 Zitieren Link zu diesem Kommentar
m43stro 10 Geschrieben 25. Januar 2008 Autor Melden Teilen Geschrieben 25. Januar 2008 @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 Zitieren Link zu diesem Kommentar
Biber 10 Geschrieben 27. Januar 2008 Melden Teilen Geschrieben 27. Januar 2008 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%\tmpfilefor /f %i in ('findstr /V /G:datei1.txt datei2.txt') do @echo %i;noid>>%temp%\tmpfileSort %temp%\tmpfile > dateiFinal.txt[/Code] Das halte ich für einen wartbaren Batch. Grüße Biber Zitieren Link zu diesem Kommentar
Biber 10 Geschrieben 28. Januar 2008 Melden Teilen Geschrieben 28. Januar 2008 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%\tmpfilefor /f %%i in (datei1.txt) do findstr "%%i" datei2.txt>nul || @echo %%i;noid>>%temp%\tmpfileSort %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 Zitieren Link zu diesem Kommentar
m43stro 10 Geschrieben 28. Januar 2008 Autor Melden Teilen Geschrieben 28. Januar 2008 Morgen Biber, danke für die Aktualisierung. apropro Wahl: Warum man Roland Koch besser nicht wählt Zitieren Link zu diesem Kommentar
m43stro 10 Geschrieben 28. Januar 2008 Autor Melden Teilen Geschrieben 28. Januar 2008 @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 Zitieren Link zu diesem Kommentar
Biber 10 Geschrieben 28. Januar 2008 Melden Teilen Geschrieben 28. Januar 2008 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- ...:FragNachINdateiSet /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 Zitieren Link zu diesem Kommentar
Empfohlene Beiträge
Schreibe einen Kommentar
Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.