Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

Mit Batchdatei aus einer .txt doppelte Zeilen löschen

Frage Entwicklung Batch & Shell

Mitglied: kostyan

kostyan (Level 1) - Jetzt verbinden

03.08.2013 um 15:04 Uhr, 3591 Aufrufe, 21 Kommentare, 1 Danke

Hallo Admins,

ich versuche mit Hilfe einer Batchdatei die Duplikate in einer .txt mit ca. 50.000 Einträgen zu löschen.
Dabei muss immer nur 1 Datensatz übrig bleiben und der doppelte Satz soll gelöscht werden.

Hinweis: Excel und Access ist keine Option, da die Struktur der .txt-Datei erhalten bleiben soll.

Also aus Duplikate.txt mit:

aaa
bbb
ccc
bbb
ccc

soll werden:

aaa
bbb
ccc


Ich habe bereits folgende Lösung hier gefunden :
http://www.administrator.de/frage/mit-batchdatei-aus-einer-txt-alle-dop ...

@echo off & setlocal
set "Datei=Daten.txt"
set "Bak=.bak"
set /a LineNo=0

move "%Datei%" "%Datei%%Bak%"
copy nul "%Datei%">nul
for /f "usebackq delims=" %%i in ("%Datei%%Bak%") do set "Zeile=%%i" & call :ProcessLine
del "%Datei%%Bak%"
goto :eof

:ProcessLine
set /a LineNo+=1
echo Validiere Zeile %LineNo% ...
findstr /b /c:"%Zeile:~,8%" "%Datei%">nul || >>"%Datei%" echo %Zeile%
goto :eof


Code funktioniert, aber leider wird bei jeder Zeile noch ein Leerzeichen am Ende eingefügt.
Hat jemand eine Idee wie man den Code ändern müsste? Oder vielleicht gibt es auch eine ganz andere Herangehensweise?
Vielen Dank im Voraus.
Mitglied: bastla
03.08.2013, aktualisiert um 15:29 Uhr
Hallo kostyan und willkommen im Forum!

Das zusätzliche Leerzeichen am Zeilenende kann eigentlich nur aus einem unbeabsichtigten Leerzeichen in der vorletzten Zeile des Batches (am Ende nach %Zeile%) resultieren - bitte überprüfen ...

Grüße
bastla

P.S.: Mit "Code"-Formatierung (lässt sich auch nachträglich noch hinzufügen) wird ein Batch besser lesbar (und mit Zeilennummern) dargestellt ...
Bitte warten ..
Mitglied: kostyan
03.08.2013 um 16:00 Uhr
Hallo bastla,

danke für die schnelle Antwort. Deine Lösung klappt super.

Mir ist aber gerade noch aufgefallen, dass der Code nicht nur doppelte Zeilen löscht:

sondern aus...

aaa
aa
a

bleibt nur übrig...

aaa
Bitte warten ..
Mitglied: Lochkartenstanzer
03.08.2013 um 16:10 Uhr
Moin,

wäre es nicht einfacher einfach ein "sort -u textdatei.txt" drauf loszulasssen, z.B. mit einem Sort aus den GnuWin32 Coreutils oder Cygwin?

just my 0,02€.

lks
Bitte warten ..
Mitglied: kostyan
03.08.2013 um 16:22 Uhr
Das soll auf einem Firmen-PC funktionieren. Ich kann also keine Programme installieren.
Bitte warten ..
Mitglied: Endoro
03.08.2013 um 16:23 Uhr
Hallo,
ich hatte diesen code mal getestet, und er hat nicht funktioniert.
Es klappt nicht zuverlässig, aus einer Datei zu lesen, in die grad geschrieben wird.

Wenn keine = Zeichen vorkommen, würde ich die Zeilen in Variable packen.
Ansonsten mit sed oder sort oder sort+uniq aus GNUWin32 die Sache angehen.
lg.
Bitte warten ..
Mitglied: Lochkartenstanzer
03.08.2013 um 17:10 Uhr
Zitat von Endoro:
Ansonsten mit sed oder sort oder sort+uniq aus GNUWin32 die Sache angehen.

"Sort -u" spart das uniq

lks
Bitte warten ..
Mitglied: Lochkartenstanzer
03.08.2013 um 17:12 Uhr
Zitat von kostyan:
Das soll auf einem Firmen-PC funktionieren. Ich kann also keine Programme installieren.

Sort.exe ist nur ein binary und muß nicht installiert werden udn könnte sogar mit eingeschränkten benutzerrechten laufen.

lks

PS: Wie ich schon an naderer Stelle sagte: Man kann an einem Auto vieles mt dem Bordwerkzeug reparieren (sofern noch welches beiliegt), aber manchmal ist angepaßtes Werkzeug doch geeigneter.

lks
Bitte warten ..
Mitglied: bastla
03.08.2013, aktualisiert um 17:46 Uhr
Hallo kostyan!
Mir ist aber gerade noch aufgefallen, dass der Code nicht nur doppelte Zeilen löscht:
Das liegt daran, dass nicht die komplette Zeile verglichen wird - so sollte das nicht mehr passieren:
01.
echo off & setlocal 
02.
set "Datei=Daten.txt" 
03.
set "Bak=.bak" 
04.
set /a LineNo=0 
05.
 
06.
move "%Datei%" "%Datei%%Bak%" 
07.
copy nul "%Datei%">nul 
08.
for /f "usebackq delims=" %%i in ("%Datei%%Bak%") do set "Zeile=%%i" & call :ProcessLine 
09.
del "%Datei%%Bak%" 
10.
goto :eof 
11.
 
12.
:ProcessLine 
13.
set /a LineNo+=1 
14.
echo Validiere Zeile %LineNo% ... 
15.
findstr /xc:"%Zeile%" "%Datei%">nul || >>"%Datei%" echo %Zeile% 
16.
goto :eof
Grüße
bastla
Bitte warten ..
Mitglied: bastla
03.08.2013, aktualisiert um 18:16 Uhr
@ Endoro
Was meinst du mit
aus einer Datei zu lesen, in die grad geschrieben wird.
Es wird doch zuerst gelesen ("findstr") und erst danach geschrieben.

Wenn Du auf Nummer sicher gehen wolltest, könntest Du aber auch in eine Temp-Datei schreiben und diese beim nächsten Schleifendurchlauf (und nochmals nach der Schleife) wieder über die "Originaldatei" "moven" ...

Grüße
bastla
Bitte warten ..
Mitglied: Endoro
03.08.2013 um 18:31 Uhr
@bastla
ich habe diesen code in XP und Win8 getestet, er funktioniert nicht:
01.
FOR /f "delims=" %%a IN (file1) DO FINDSTR /lxc:"%%a" file2 >NUL 2>&1|| >>file2 (ECHO(%%a)
Es entsteht eine 1:1 Kopie, mit allen Duplikaten.
lg.
Bitte warten ..
Mitglied: bastla
03.08.2013, aktualisiert um 18:50 Uhr
@ Endoro
Die Entsprechung zum Code oben wäre aber
FOR /f "delims=" %%a IN (file1) DO FINDSTR /lxc:"%%a" file2 >NUL 2>&1|| >>file2 ECHO %%a
Die leere "file2" hattest Du natürlich vorweg schon erzeugt ...

Grüße
bastla
Bitte warten ..
Mitglied: Endoro
03.08.2013 um 18:55 Uhr
@bastla,
die Klammern sind da nur zur Sicherheit.
Bei diesem code
01.
@ECHO OFF &SETLOCAL 
02.
TYPE nul>file2 
03.
TYPE nul>file3 
04.
FOR /f "delims=" %%a IN (file1) DO ( 
05.
	MOVE file3 file2 
06.
	FINDSTR /lxc:"%%a" file2 >NUL 2>&1|| >>file2 ECHO(%%a 
07.
	MOVE file2 file3 
08.
09.
MOVE file3 file2 
10.
FC file1 file2
entsteht auch eine 1:1 Kopie :/
lg.
Bitte warten ..
Mitglied: bastla
03.08.2013, aktualisiert um 19:04 Uhr
Hallo Endoro!

Irgendwo (vorzugsweise nach dem "||") in der Zeile
FINDSTR /lxc:"%%a" file2 >NUL 2>&1|| >>file2 ECHO(%%a 
sollte in diesem Fall "file3" vorkommen . Die Zeile 7 würde ich ganz einsparen.
Die Sicherheitsvariante (wegen allfälliger Sonderzeichen) sähe bei mir so aus:
01.
copy nul file2>nul 
02.
FOR /f "delims=" %%a IN (file1) DO ( 
03.
    set "Zeile=%%a" 
04.
    setlocal enabledelayedexpansion 
05.
    FINDSTR /lxc:"!Zeile!" file2 >NUL 2>&1||>>file2 ECHO !Zeile! 
06.
    endlocal 
07.
)
Einzig Leerzeilen bleiben (in allen bisherigen Versionen) auf der Strecke ...

Grüße
bastla
Bitte warten ..
Mitglied: Endoro
03.08.2013 um 19:10 Uhr
Es hilft nix, es geht nicht :/
01.
@ECHO OFF &SETLOCAL 
02.
TYPE nul>file2 
03.
TYPE nul>file3 
04.
FOR /f "delims=" %%a IN (file1) DO ( 
05.
	FINDSTR /lxc:"%%a" file2 >NUL 2>&1|| >>file3 ECHO(%%a 
06.
	copy file3 file2 >nul 
07.
08.
FC file1 file2
.. lässt sich nicht überlisten.
lg.
Bitte warten ..
Mitglied: bastla
03.08.2013 um 20:19 Uhr
Hallo Endoro!

Kann ich nicht nachvollziehen - bei mir funktioniert auch diese Variante (getestet unter XP) ...

BTW: Die Klammer nach "ECHO" ist nicht nötig, da "%%a" nicht leer sein kann (darum werden ja auch Leerzeilen nicht in die Ergebnisdatei übernommen).
Mit meinem Ansatz oberhalb hast Du auch keinen Erfolg?

Grüße
bastla
Bitte warten ..
Mitglied: Endoro
03.08.2013, aktualisiert um 22:18 Uhr
@bastla,
ich habe jetzt mal die source gewechselt, und es geht.
Es lag an meinem Testfile, mit dem es nicht geht.
Ich hab's hier hochgeladen, das Forum zeigt es nicht ordentlich an.
Mit XML (oder ähnlichem) darf man also nicht unterwegs sein, was die Nützlichkeit einschränkt.

Zitat von Lochkartenstanzer:
"Sort -u" spart das uniq

Am einfachsten wäre awk, da bleibt die Reihenfolge (anders als bei sort) erhalten
01.
awk "!($0 in a); a[$0]" file1 > file2
lg.

PS: Leerzeilen werden wie andere Zeilen behandelt, die erste wird ausgegeben, Duplikate nicht.
Bitte warten ..
Mitglied: bastla
03.08.2013, aktualisiert um 21:59 Uhr
Hallo Endoro!

Batch mag in bestimmten Fällen Anführungszeichen als Textbestandteil noch weniger als andere Sonderzeichen (und "<" und ">" haben in "findstr" auch spezielle Funktionen) ...

Eine VBS-Alternative (die allerdings voraussetzt, dass die gesamte Ergebnisdatei in den Arbeitsspeicher passt) sähe etwa so aus:
01.
Ein = "file1" 
02.
Aus = "file2" 
03.
 
04.
Set fso = CreateObject("Scripting.FileSystemObject") 
05.
Set DateiEin = fso.OpenTextFile(Ein) 
06.
Ergebnis = vbNewline 
07.
Do Until DateiEin.AtEndOfStream 
08.
    Zeile = DateiEin.ReadLine 
09.
    If Zeile <> "" Then 'Leerzeile 
10.
        If InStr(Ergebnis, vbNewline & Zeile & vbNewline) = 0 Then Ergebnis = Ergebnis & Zeile & vbNewLine 
11.
    Else 
12.
        Ergebnis = Ergebnis & Zeile & vbNewLine 
13.
    End If 
14.
Loop 
15.
fso.CreateTextFile(Aus).Write Mid(Ergebnis, 3)
Hier würden (alle) Leerzeilen auch im Ergebnis aufscheinen.

Grüße
bastla
Bitte warten ..
Mitglied: klausph
26.08.2015 um 12:06 Uhr
guten tag endoro (und alle anderen beteiligten

ich war gestern (im jahre 2015) auf der suche einem kommandozeilentool, was obige aufgabe erledigen soll (=sortieren, alle doppelten zeilen, bis auf die erste zeile, sollen gelöscht werden).
Lochkartenstanzer hat uniq.exe aus den gnutools_irgendwas empfohlen. hat bei mir nicht gekappt!
deine lösung mit awk bekomme ich ebenfalls nicht zum laufen, auch meine schlauen bücher zum thema awk helfen mir nicht weiter; bekommt man wirklich DEINE zeile SO unter win32 zum laufen? ich sach mal: nein

deshalb habe ich einige stunden gestern verbraucht, frauchen war sauer! und voila:
aber allen interessierten stelle ich jetzt mal "meine" lösung vor:

und sie ist so simpel!

1. erst mal sortieren, da gibt es ja einige programme...
und dann:

2. uniq.exe %tmp%\1 %tmp%\2
er löscht sehr schnell aus 1 die doppelten einträge raus!, und belässt in 2 den ersten drin!
die bedingung ist !aber!: zuerst sortieren!

uniq.exe ist ein programm aus dem paket: (Get)GnuWin32. und man benötigt mindesten diese dll dazu:
libintl3.dll (sorry, kann sein, daß es da noch eine zweite gibt...) DAS ist relativ großer nachteil von den gnu(nur von den?)-produkten: man darf nie die externen dll's vergessen.

nachsatz zum sortieren:
ich benutze das asort.exe aus der "bibliothekswelt", aus allegro-C. das ist nicht publicdomain. aber es gibt andere sorter, erstens dan von MS, sowie GNU und co. das dürfte NICZT das problem sein.....

viele grüße, klaus
Bitte warten ..
Mitglied: reckheim
26.08.2015 um 15:27 Uhr
Hallo
ich schreibe lange Übersetzungsprogramme in FoxPro in unten folgender Text-Datei-Form.
Die Datei ist allerdings durch Zusammenführung verschiedener Versionen voller Duplikate, welche gelöscht werden sollen.
Die Reihenfolge und alle Zeichen müssen unbedingt eingehalten werden.

Was für ein batch kommt da infrage ?



*
...
update papworth set deut = STRTRAN(deut,"cantoned", "bewink.")
update papworth set deut = STRTRAN(deut, 'waved & ', " gewellt u. ")
RETURN

Funktion frut
update papworth set deut = STRTRAN(deut,"cantoned", "bewink.")
RETURN

Funktion Klammer
*update papworth set deut = STRTRAN(deut,"]", "")
*update papworth set deut = STRTRAN(deut,"{ ", "{")
*update papworth set deut = STRTRAN(deut," }", "}")
*update papworth set deut = STRTRAN(deut,"( ", "(")
*update papworth set deut = STRTRAN(deut," )}", ")")
*update papworth set deut = STRTRAN(deut," ", " ")
*update papworth set deut = STRTRAN(deut," ", " ")
update papworth set deut = STRTRAN(deut," ;", ";")
update papworth SET deut = STRTRAN(deut,' &;',';')
RETURN
*
Bitte warten ..
Mitglied: Endoro
26.08.2015 um 17:50 Uhr
Zitat von reckheim:

Hey, du müsstest einen neuen Thread erstellen, hier findet dich sonst niemand .


Zitat von klausph:

deine lösung mit awk bekomme ich ebenfalls nicht zum laufen, auch meine schlauen bücher zum thema awk helfen mir nicht
weiter; bekommt man wirklich DEINE zeile SO unter win32 zum laufen? ich sach mal: nein
Ja, nur unter Windows, für Bash müssen die doppelten durch einfache Quotas ersetzt werden.

Gruss, Endoro
Bitte warten ..
Mitglied: klausph
27.08.2015 um 09:50 Uhr
@reckheim
du "MUSST" das selber ausprobieren. das forum ist so voller ideen und lösungsansätze.

ich habe gestern ca 3-5 stunden gebraucht, um auf "meine" simple lösung zu kommen.

bin übrigens der meinung, daß die meinige auprobieren solltest.
je nach dem, welchen sorter du erwischt, kannst du den sorter auch auf die zu positionierende stelle setzen.(deine sternchen's könnten wichtig sein)
(ich glaube der windows-sorter kann das.) egal, das "MUSST" du selber rausfinden.

meine philosophie: 20 zeilen präsentieren, nach der geeigneten lösung fragen, ist nichts für die gehirnzellen.
selber denken, probieren, UND dann wenn man nicht weiterkommt, "klug" fragen
capisce?

grüße

ps: mir hat dieses forum schon sooo viel gebracht.
nebenbei: ich hoffe, auch anderen durch meine lösungen und ansätze geholfen zu haben. oooh, was habe ich schon für for-schleifen gemacht, dank des tutorials, was es hier zu for gibt. und wenn wirklich mal jemand mir eine lösung "fertig" präsentiert hat, solche "verrückten" gibt es hier, die setzen sich stunden hin, basteln die schönsten scripte, und voila! .. der satz geht weiter: ...präsentiert hat, dann wird er auch in meinem script mit copyright genannt. nebenbei2: sollte ich mit den lösungen geld verdienen, wird der urheber daran beteiligt! oder mindestens zum bierrundgang in die radeberger brauerei eingeladen!
Bitte warten ..
Neuester Wissensbeitrag
Heiß diskutierte Inhalte
Windows Userverwaltung
Ausgeschiedene Mitarbeiter im Unternehmen - was tun mit den AD Konten? (33)

Frage von patz223 zum Thema Windows Userverwaltung ...

LAN, WAN, Wireless
FritzBox, zwei Server, verschiedene Netze (21)

Frage von DavidGl zum Thema LAN, WAN, Wireless ...

Viren und Trojaner
Aufgepasst: Neue Ransomware Goldeneye verbreitet sich rasant (20)

Link von Penny.Cilin zum Thema Viren und Trojaner ...