mihail
Goto Top

Durchsuchen alle Zeilen einer Textdatei und die gleiche Zeilen herausfiltern und anzeigen

Guten Abend,
Ich melde mich ernuet mit der Bitte mir falls möglich zu helfen.
Ich muss aus einigen txt-Dateien die sehr viele eingescannte Zeilen enthalten, herausfinden ob Wiederholungen zu finden sind.
Die Zeilen sind vorab nummeriert und schauen so aus:

1: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0001
2: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0002
3: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0003
4: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0004
5: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0005
6: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0006
7: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0006
8: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0008
9: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0009
10: ABCDEFGHIJKLMNOPQRS#01T#abcdef_yymmdd0010
11: etc

yymmdd = Datum, hier absichtlich die Zeile 7: ist = Zeile 6:.
Da es um hunderten von Zeilen sich handelt können möglicherweise die laufende Nummer aus versehen sich oft wiederholen (man hat daneben mit dem Scanner gezielt, oder wurde bei der Arbeit gestört, etc...).
Ich hätte gerne die Zeilen wo die Scandaten sich wiederholen herausfiltern und zwar deren Nummer (z.B. hierzu die 7: und evtl auch die laufende Nr.die falsch gescannt wurde, hierzu 0006 signalisieren.
Ich versuche seit einer geräumen Zei etwas zu erstellen aber ofensichtlich meine Kenntnise reichen dafür nicht aus. Ich habe auch auf diese IE-Seite und auch allgemein im Internet viel gesucht aber entweder habe ich nicht die richtige Suchbegriffe genannt oder gibt es wirklich kein Thema darüber.
Ich fürchte, dass das Problem einfach zu lösen ist aber hilft nichts, ich kann es selber nicht lösen.
Kann mir jemand bei dem Problem helfen?
Vielen Dank,

Content-Key: 311943

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

Printed on: April 25, 2024 at 00:04 o'clock

Mitglied: 129813
Solution 129813 Aug 06, 2016 updated at 18:48:33 (UTC)
Goto Top
Powershell
$txt = 'C:\data.txt'  
$unique = @()
gc $txt | %{
    $data = $_.Split(" ",2)[1]  
    if($data -in $unique){
        "Duplicate in row $($_.Split(":")) with running number $($_.Substring($_.Length-4))"  
    }else{$unique += $data}
}
Regards
Member: Mihail
Mihail Aug 06, 2016 at 20:27:50 (UTC)
Goto Top
Hello highload,
Thanks so much for your help. You've helped me last time with my first question in this forum too. Unfortunately I do not know and do not yet understand anything Powershell script. To this I should espouse my new knowledge and this will last for a while. There is no direct possibility of a solution to the CMD batch ? Or if otherwise not work I ask myself how to start a powershell script from a batch ? How can I call a powershell script from a cmd batch ? I gotta study the problem a little .
Thanks again for your help ,
Best regards,
Member: rubberman
Solution rubberman Aug 06, 2016 updated at 22:29:54 (UTC)
Goto Top
Hallo Mihail.

PowerShell Scripts haben die Endung .ps1
Wenn du es aus einem Batchscript aufrufen willst, dann bspw. so:
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '.\test.ps1'"
... mit "test.ps1" im gleichen Verzeichnis wie deine Batchdatei.

Eine Lösung per Batch ist sicher auch denkbar, aber ungleich komplizierter und nicht empfehlenswert.
Bspw.
@echo off &setlocal
set "txtfile=scan.txt"  

for /f "usebackq tokens=1* delims=:" %%i in ("%txtfile%") do (  
  set "check="  
  for /f "tokens=1* delims=:" %%k in ('findstr /nec:":%%j" "%txtfile%"') do if %%k gtr %%i (  
    set "line=%%l"  
    setlocal EnableDelayedExpansion
    echo(!line!|findstr /vbc:"%%i:" >nul && if not defined check (set "check=1" &echo Duplicate in row %%k with running number !line:~-4!)  
    for /f %%l in ("!check!") do endlocal &set "check=%%l"  
  )
)
pause

Grüße
rubberman
Member: Mihail
Mihail Aug 07, 2016 at 06:39:43 (UTC)
Goto Top
Hallo rubberman,

Danke vielmals für Deine schnelle Hilfe und für den guten Rat. Ich werde zuerst den batch-Script testen weil mich Deine Lösung zu verstehen sehr interessiert . Daran habe ich mir viele Gedanken gemacht aber leider keine funktionierende Lösung gefunden. Ich werde bestimmt auch den Powershell-Script von highload auch testen und auch hier versuchen zu verstehen aber dafür brauche ich noch ein wenig Zeit weil nicht sowit bin. Zur Zeit bemühe ich mich Einiges auf die Beine zu stellen und dafür muss ich zuerst unbedingt von der Logik her mehr lernen.

Vielen Dank und Dir und allen hier einen schönen Tag,
Grüße,
Mihail
Member: Mihail
Mihail Aug 07, 2016 at 07:30:53 (UTC)
Goto Top
Hallo rubberman,

Also, Deine Lösung ist zumindest für mich ein Meisterstück! Die funktionierte sofort und bringt es mir natürlich einiges bezüglich der Syntax und Denkweise bei. Ich muss auch zugestehen, dass ich weit entfernt von Deiner Lösung war und das ist zur Zeit mein Problem. Ich bin einfach nicht soweit mit anderen Scriptlösungen mich zu beschäftigen.
Nochmals vielen Dank,
Viele Grüße,

Mihail
Member: colinardo
Solution colinardo Aug 07, 2016 updated at 09:03:38 (UTC)
Goto Top
Hallo Mihail,
und beiden Welten (Batch/Powershell) kombiniert in deiner Batch als Quasi Einzeiler (wenn man von der Deklaration der Variablen absieht):
@echo off
set "textfile=C:\data.txt"  
powershell -NoProfile -ExecutionPolicy Bypass -Command "gc '%textfile%'' | group {$_.Split(':',2)[1]} | ?{$_.Count -gt 1} | %%{$_.group | select -skip 1| %%{\"Duplicate in row $($_.Split(':')) with running number $($_.Substring($_.Length-4))\"}}"  
Der Batch-Powershell Code macht nichts anderes als alle Zeilen deiner Textdatei einzulesen, dann an das CMDLet group-object zu übergeben welches die Zeilen gesplittet am Doppelpunkt vergleicht und gruppiert um dann nur die Gruppen zu übernehmen bei der mehr als 2 Zeilen existieren und aus diesen dann nur alle doppelten Zeilen auszugeben.

Grüße Uwe

p.s. Powershell macht richtig Spaß wenn du die ersten Hürden überwunden hast. Es ist definitiv einen zweiten Blick wert, zumal sie unter Windows Betriebsystemen schon seit langem zum Standard geworden ist und erheblich Schreibarbeit und Entwicklungszeit einspart.
Member: rubberman
rubberman Aug 07, 2016 at 11:21:24 (UTC)
Goto Top
Hallo Mihail

Mein Beispiel sollte dich eigentlich eher davon abhalten, Batch lernen zu wollen. Mit PowerShell kommst du viel einfacher zum Ziel. Batch bietet viel weniger Möglichkeiten und darum musst du viel zu oft quer denken da es keine direkte Lösung gibt, must Aktionen vielfach ausführen (wie meine FINDSTR Aufrufe) was Zeit raubt und einiges ist einfach gar nicht erst mit Batch machbar oder so unsicher oder aufwendig, dass es einfach nicht empfehlenswert ist. Mit PowerShell hast du alle Möglichkeiten von .NET (anders gesagt, alles was du mit C# umsetzen kannst, geht grundsätzlich auch mit PowerShell).

Ich habe mich schon vor 25 Jahren unter DOS mit Batch beschäftigt. Deshalb sind die Voraussetzungen etwas anders. Keine Ahnung, wie viele Hundert Batchschnipsel ich für unterschiedliche Problemlösungen bereits gesammelt habe. Wenn ich heute noch einmal mit Scripting starten würde, wäre weder Batch, noch VBScript eine Option. PowerShell bietet einfach so überragende Möglichkeiten, dass nichts anderes infrage kommen würde...

Grüße
rubberman
Member: Mihail
Mihail Aug 07, 2016 at 13:37:14 (UTC)
Goto Top
Hallo rubermann,

Danke für Deine erneute Antwort. Hätte nicht mal gedacht, dass Du mir noch da eine Antwort schenkst. Ich bin mir sicher, dass Du recht hast, schließlich ist Batch eine alte Geschichte und deshalb werde ich Deinen Rat folgen. Ich brauche einfach noch ein wenig Zeit dafür vor allem auch weil es um ein ganz neues Terrain für mich sich handelt.

Viele Grüße und einen schönen Abend,

Mihail
Member: Mihail
Mihail Aug 07, 2016 at 13:52:59 (UTC)
Goto Top
Hallo Uwe,

Bitte entschuldige meine verspätete Antwort.
Dein Script bedeutet für mich eine sehr, sehr interessante Lösung. Ich denke, dass Du wie rubermann auch recht habt und ich werde in der Welt von PowerShell einsteigen um damit mein Glück zu versuchen.
Ich dachte immer, dass dafür muss man eine batch Basis zuerst verschaffen sonst versteht man gar nichts mehr.
Auf jeden Fall ich muss zugestehen, dass extrem beeindruckt von dem Hilfeangebot bin vor allem wenn dieses von Profis kommt.
Ich danke Dir vielmals für die Hilfe , ausführliche Erklärung der Lösung, für die ermutigende Worte und somit für die Zeit die Du mir verschenkt hast.

Einen schönen Abend,
Viele Grüße,

Mihail
Member: Mihail
Mihail Aug 31, 2016 at 16:31:56 (UTC)
Goto Top
Hallo rubbermann,

Bitte entschuldige, dass ich Dich mit einer neuen Frage nochmals behellige.
Ich hoffe, dass Du noch an meine Frage von 07.08.22016 „Durchsuchen alle Zeilen einer Textdatei und die gleiche Zeilen herausfiltern und anzeige“ und Deine für mich sehr geschätzte Losung erinnerst.
Ich versuche in der letzten Zeit mit viel Mühe und Untersuchungen über diese Site und auch allgemein über Internet zu einer Lösung zu kommen aber dummerweise muss ich ehrlich sagen, dass ich wieder nicht weiter gekommen bin. In meinem Projekt ist eine neue Situation zustande gekommen in dem einige Duplikate in einer Datei entstehen müssen aber sowohl diese samt original Zeile unbedingt gelöscht werden müssen.
Als Beispiel in den folgende Textdatei sind auf die Positionen 11, 12 und 13 die duplizierte Zeilen der Positionen 2, 6, 10 zu sehen.
Alle Zeilen sind von einem TAB gefolgt.

1: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230012
2: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230013
3: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230014
4: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230015
5: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230016
6: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230017
7: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230018
8: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230019
9: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230020
10: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230021
11: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230013
12: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230017
13: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230021

Nach der „Säuberungsaktion“ muss die Datei (möglich auch eine andre Datei z.B. out_%intxtfile%.

1: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230012
2: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230014
3: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230015
4: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230016
5: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230018
6: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230019
7: ABCDEFGIJKLMNOPRS#01A#abcdef_ttmmjj_1607230020

Ich habe versucht unter anderen unzählige Tests auch Deinen Script dafür zu verwenden in dem ich ihn so modifiziert habe:

for /f "usebackq tokens=1* delims=: " %%i in ("%txtfile%") do (
set "check="
for /f "tokens=1* delims=: " %%k in ('findstr /nec:":%%j" "%txtfile%"') do if %%k gtr %%i (
set "line=%%l"
setlocal EnableDelayedExpansion
echo(!line!|findstr /vbc:"%%i: " >nul && if not defined check (set "check=1" & type "%txtfile%" |findstr /v "%%l">logout.txt)
for /f %%l in ("!check!") do endlocal &set "check=%%l"
)
)

aber es mir lediglich nur gelungen die Zeile 13: zu löschen und weiter nichts. Es ist mir klar, dass ich das Thema „Lesen mehreren Variablen in mehreren Zeilen um danach diese zu manipulieren z.B. löschen oder ersetzen“ zumindest in so einem Fall nicht beherrsche.
Könntest Du mir hierzu erneut helfen?

Vielen Dank und Grüße,

Mihail
Member: rubberman
Solution rubberman Aug 31, 2016 at 22:00:10 (UTC)
Goto Top
Hallo Mihail

Ich hoffe, dass Du noch an meine Frage von 07.08.22016
Ich bin froh wenn ich noch weiß was gestern war face-wink

@echo off &setlocal
set "txtfile=test.txt"  

set "lnums="  
for /f "usebackq tokens=1* delims=:" %%i in ("%txtfile%") do (  
  for /f %%k in ('type "%txtfile%"^|find /c ":%%j"') do if %%k gtr 1 call set "lnums=%%lnums%%%%i,"  
)

set "n=0"  
>"%txtfile%~" (  
  for /f "usebackq tokens=1* delims=:" %%i in ("%txtfile%") do (  
    set "check="  
    for %%k in (%lnums%) do if %%i==%%k set "check=1"  
    if not defined check (
      set /a "n+=1"  
      for /f %%k in ('set /a n') do echo %%k:%%j  
    )
  )
)

::move /y "%txtfile%~" "%txtfile%"  
Die Ausgabe wird in eine Datei geschrieben, die so heißt wie die Eingangsdatei, aber mit angehängter Tilde. Wenn du dort die korrekte Ausgabe finden solltest, entferne die beiden Doppelpunkte vor der letzten Codezeile. Dann wird die Originaldatei ersetzt.

Grüße
rubberman
Member: Mihail
Mihail Sep 01, 2016 at 17:25:41 (UTC)
Goto Top
Guten Abend rubberman,

Danke vielmals für die prompte und große Hilfe. Du hast für mich, vor allem zu so einer späteren Zeit in der Nacht eine Antwort bereit gestellt. Ich kann wirklich nicht viel kommentieren weil zuerst muss ich verstehen was und wie Du es gemacht hast. Eines glaube ich zumindest habe ich gecheckt: Du hast einen anderen Weg gewählt (die überflüssige Zeilen nicht löschen sondern einfach "übersehen" ) und wenn so ist war dieser Weg bestimmt besser dafür geeignet. Tja, neben der enormen Kenntnisen hierzu muss man das es auch noch können.
Getestet habe ich den Script schon aber ehrlich gesagt werde ich noch eine Weile brauchen bis ich ihn verstanden habe. Vielleicht werde ich danach es sagen können, dass ich davon viel gelernt habe, momentan kämpfe ich mit der Art und Weise wie Du die Befehle innerhalb der "for Schleife" verwendet hast.
Wie auch immer, Du hast mir erneut sehr viel geholfen und das beeindruckt mich noch mehr während diese Site zu einer der besten die ich je besucht habe macht.

Nochmals vielen Dank und einen schönen Abend,

Viele Grüße,

Mihail
Member: rubberman
Solution rubberman Sep 01, 2016 updated at 18:30:46 (UTC)
Goto Top
Hallo Mihail.

vor allem zu so einer späteren Zeit
Was wohl der Grund ist, warum das Script noch etwas zu kompliziert geworden ist.

Getestet habe ich den Script schon aber ehrlich gesagt werde ich noch eine Weile brauchen bis ich ihn verstanden habe.
Ist nicht kompliziert. Der Schlüssel ist die Option /C von FIND. Ein
type "Dateiname"|find /c "String"
gibt direkt die Anzahl der gefundenen "String"s in der Datei als Zahl aus.

Hier mal die vereinfachte Version mit Kommentaren (REM).
@echo off &setlocal
REM Dateiname
set "txtfile=test.txt"  

REM neue Zeilennummer
set "n=0"  
REM temporäre Ausgabedatei
>"%txtfile%~" (  
  REM jede Zeile in Zeilennummer (%%i) und restliche Zeile hinter dem Doppelpunkt (%%j) trennen
  for /f "usebackq tokens=1* delims=:" %%i in ("%txtfile%") do (  
    REM zählen, wie oft der Rest der Zeile (: und %%j) in der Datei vorkommt. Wenn nur einmal, dann ...
    for /f %%k in ('type "%txtfile%"^|find /c ":%%j"') do if %%k==1 (  
      REM neue Zeilennummer um 1 erhöhen
      set /a "n+=1"  
      REM neue Zeilennummer in %%l zwischenspeichern und zusammen mit : und dem Rest der Zeile ausgeben
      for /f %%l in ('set /a n') do echo %%l:%%j  
    )
  )
)

REM Datei durch die temporäre Datei ersetzen
move /y "%txtfile%~" "%txtfile%"  
Grüße
rubberman
Member: Mihail
Mihail Sep 01, 2016 at 19:24:25 (UTC)
Goto Top
Hallo rubberman,

gerade war ich am "Überlegen" und Testen in Verbindung mit meinem gesamten Script.
Jawohl, das ist super, das wird mir weiterhelfen vor allem wurde alles durch die Kommentare leichter für mich zu verstehen.
Am schwierigsten ist so "bandbreitig" aber zugleich auch sehr einfach zu denken!
Ich habe in meine Untersuchungen über Internet irgendwann ein Spruch von Albert Einstein gelesen. Der hat es mir sehr gut gefallen und passt in dem Fall sehr gut zu Dir.
Der lautet so ungefähr:
“Any intelligent person can make things bigger and more complex... It takes a touch of genius - to move in the opposite direction”

Vielen Dank nochmals, ich werde falls es Dir nicht viel ausmacht eine oder andere Frage noch stellen in der Hoffnung, dass Du dafür Zeit für mich erneut nehmen kannst.

Viele Grüße,

Mihail
Member: rubberman
rubberman Sep 01, 2016 at 20:21:01 (UTC)
Goto Top
Haha, danke für die Blumen, Mihail.

Wäre ich so ein Genie, wäre ich in der Lage dir einen PowerShell-Einzeiler zu diesem Zweck zu schreiben. Nevermind ... face-wink

rubberman
Member: colinardo
colinardo Sep 06, 2016 updated at 15:10:34 (UTC)
Goto Top
Zitat von @rubberman:
Wäre ich so ein Genie, wäre ich in der Lage dir einen PowerShell-Einzeiler zu diesem Zweck zu schreiben. Nevermind ... face-wink
Hahaha der war gut, graue Haare hab ich zwar auch schon diverse, aber "den ultimativen Geistesblitz" nach dem Griff in die Steckdose hatte ich dann doch noch nicht face-big-smile.

@Mihail Wenns das dann war, den Beitrag bitte noch auf gelöst setzen. Merci.
Member: Mihail
Mihail Sep 06, 2016 at 16:40:33 (UTC)
Goto Top
Hallo Uwe,

Danke für die Erinnerung. Es tut mir Leid ich habe es einfach übersehen.

Mihail