.txt Datein die bestimmten String enthalten ausgeben.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
smoothcode
User
Beiträge: 4
Registriert: Donnerstag 5. Juni 2014, 09:49

Servus allerseits,

folgendes Problem, ich habe ein Verzeichnis mit 10 .txt/Text Dateien, davon
enthalten 5 .txt Datein im Header einen String namens "WNR" in der ersten Zeile.

Ich möchte nur die .txt Datein via Print ausgeben die diesen String enthalten.

Danach die Zeilenanzahl mit Count jeder einzelnen Datei bestimmen.

Wie wäre das einfach möglich?

Ich habe hier schonmal was gebaut..

Code: Alles auswählen

import glob   
path = 'work/*.txt'   
files=glob.glob(path)   
for file in files:     
    f=open(file, 'r')  
    print '%s' % f.readlines()   
    f.close()
Zuletzt geändert von Anonymous am Donnerstag 5. Juni 2014, 10:03, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@smoothcode: Brich das Problem in kleinere Unterprobleme herunter und schreibe dann jeweils eine Funktion die ein Teilproblem löst. Wenn Du die Funktionen getestet hast, kannst Du sie zu einer grösseren (Teil)Lösung zusammen setzen. Solange bis das gesamte Problem gelöst ist.

Anmerkungen zum Quelltext: `files` und `file` passen als Namen nicht zum jeweiligen Wert, weil es sich nicht um Dateien handelt sondern nur um Datei*namen*. Ein Datei-Objekt ist das was man von `open()` als Rückgabewert bekommt.

Dateien sollte man wenn möglich zusammen mit der ``with``-Anweisung öffnen, damit sie unter allen Umständen auch am Ende des ``with``-Blocks wieder geschlossen werden.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

smoothcode hat geschrieben:

Code: Alles auswählen

[...]
    print '%s' % f.readlines()
[...]
Es sieht schwer so aus, als sei diese Zeile der Ansatzpunkt. Ersetze sie durch eine Funktion, die über alle Zeilen der Datei läuft (und dabei in der ersten Zeile auf das Vorhandensein von 'WNR' prüft) und diese gegebenenfalls zählt und ausgibt.

Für den grundsätzlichen Ansatz würde mir folgendes einfallen.

Code: Alles auswählen

def do_work(textfile):
    for linenumber, text in enumerate(textfile):
        [...]
Die Schleife kannst du verlassen, wenn du in der ersten Zeile den gesuchten String nicht findest. Falls doch, dann gibst du einfach die Zeilen aus und kannst am Ende über linenumber auch noch die Zahl der Zeilen ermitteln.

Ich würde das wohl noch etwas feiner granulieren, aber für einen ersten Ansatz reicht das.
smoothcode
User
Beiträge: 4
Registriert: Donnerstag 5. Juni 2014, 09:49

Code: Alles auswählen

import glob
import os
os.chdir( "work" )
for file in glob.glob('*.TXT'):
    with open(file) as f:
        contents = f.read()
    if 'WNR' in contents:
	f.close()
	
        print file
Damit bekomme ich auf jedenfall alle Datein mit dem String WNR.

So müsste ich jetzt unter dem Code die Datei wieder Counten, die elegantere Lösung wäre
so wie ich denke, nen readline sowie den String finden in einem Rutsch.
Zuletzt geändert von smoothcode am Donnerstag 5. Juni 2014, 10:52, insgesamt 1-mal geändert.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@smoothcode
1. Würde ich Dateien immer mit dem ``with`` statement öffnen. Damit stellst Du sicher, dass die Datei in jedem Fall auch wieder ordentlich geschlossen wird.
2. Wenn Du die Datei offen hast, nimmst Du die erste Zeile via `readline()` und schaust mit dem ``in`` Operator (wie hier dokumentiert) nach, ob sich der String 'WNR' darin befindet.
3. Nun ermittelst Du die Anzahl der Zeilen. Das würde ich mit `enumerate()` lösen. Diesem Wert addierst Du noch mit 1, da Du Dich durch das Lesen der ersten Zeile bereits auf der Zweiten befindest.
3. Somit hast Du alle Informationen, um die weitere Ausgabe zu steuern.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
smoothcode
User
Beiträge: 4
Registriert: Donnerstag 5. Juni 2014, 09:49

Fragt sich wie ich das Codemässig umsetze mit ReadLine..
BlackJack

@smoothcode: Lass die Finger von `os.chdir()`. Das verändert das Arbeitsverzeichnis für den gesamten Prozess. Mit solchen Spässen sollte man gar nicht erst anfangen, weil einen das irgendwann ganz furchtbar in den A** beisst wenn man Dateioperationen in einem Arbeitsverzeichnis ausführt mit dem man so nicht gerechnet hat.

Dein Test prüft nicht ob 'WNR' in der ersten Zeile steht, sondern ob es *irgendwo* in der gesamten Datei steht. Dazu wird die gesamte Datei in den Speicher gelesen. Auch die Dateien bei denen kein 'WNR' in der ersten Zeile steht, wo man also gar nicht über die erste Zeile hinaus lesen müsste.

Wenn man Dateien mit ``with`` zusammen öffnet, dann braucht man kein `close()` mehr, das erledigt die ``with``-Anweisung ja gerade für einen. An *der* Stelle im Programmfluss wäre ein Schliessen der Datei auch unpassend, denn wenn ``with`` das nicht schon machen würde, dann würdest Du so nur Dateien schliessen, die 'WNR' enthalten, und alle anderen nicht.

Statt `readline()` wie vorgeschlagen wurde, würde ich die `next()`-Funktion verwenden. Das ist universeller, weil das bei jedem iterierbaren Objekt funktioniert und nicht nur bei Dateiobjekten.

Der Name `f` ist zu kurz und nichtssagend. Hier würde sich zum Beispiel `lines` anbieten.

Zum ermitteln der Anzahl von Elementen in einem iterierbaren Objekt kann man auch die `sum()`-Funktion mit einem Generatorausdruck verwenden um 1 für jedes Objekt im „iterable” aufzusummieren.
smoothcode
User
Beiträge: 4
Registriert: Donnerstag 5. Juni 2014, 09:49

Ok ich versuche es.
BlackJack

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import print_function
from glob import iglob


def main():
    for filename in iglob('work/*.txt'):
        with open(filename, 'r') as lines:
            if 'WNR' in next(lines):
                # 
                # Add 1 because of the first line already consumed by the test.
                # 
                line_count = sum(1 for _ in lines) + 1
                print('{0!r} contains {1} lines'.format(filename, line_count))
    

if __name__ == '__main__':
    main()
Antworten