Forum: PC-Programmierung Python - Zeilen mit Wörter ausgeben


von Jason (Gast)


Lesenswert?

Guten Morgen,

ich habe eine txt-Datei mit Schlüsselwörtern:

String1,
String2,
String3

Für eine Filterfunktion benötige ich diese Strings in folgender Form: 
String1|String2|String3

Meine Lösung:
1
data=open("keywords.txt").readlines()
2
for n,line in enumerate(data):
3
    if line.startswith("line"):
4
       data[n] = "\n"+line.rstrip()
5
    else:
6
       data[n]=line.rstrip()
7
search_keywords='|'.join(data)
8
print ('Keywords: ', search_keywords)

Es funktioniert auch, aber wenn ich in der Textdatei aus Versehen 
Leerzeilen einfüge, erscheint folgende Ausgabe: String1|String2|String3| 
| |

Dadurch funktioniert der Filter nicht mehr richtig. Gibt es eine 
Möglichkeit, diese Leerzeilen in python zu ignorieren, damit ich eine 
sinnvolle Ausgabe erhalte?

von Joachim S. (oyo)


Lesenswert?

Dein Problem liegt vermutlich darin, dass Du die gestripten etc. Daten 
in-place in das ursprüngliche Array zurückschreiben willst. Das ist aber 
eine blöde Idee, weil das Array eben Einträge enthält, die 
herausgefiltert werden sollen. Erzeuge also lieber ein neues Array.

Das hier sollte funktionieren:
1
data = []
2
for line in open('keywords.txt').readlines():
3
  line = line.rstrip()
4
  if len(line) > 0:
5
    if line.startswith('line'):
6
      line = '\n' + line
7
    data.append(line)
8
search_keywords = '|'.join(data)
9
print('Keywords: ', search_keywords)

von imonbln (Gast)


Lesenswert?

Joachim S. schrieb:
> if len(line) > 0:
>     if line.startswith('line'):

das len(line) > 0 ist in Python nicht nötig
1
   if line:
2
     if line.startswith('line'):

reicht auch

Jason schrieb:
> Für eine Filterfunktion benötige ich diese Strings in folgender Form:
> String1|String2|String3
>
> Meine Lösung:data=open("keywords.txt").readlines()
> for n,line in enumerate(data):
>     if line.startswith("line"):
>        data[n] = "\n"+line.rstrip()
>     else:
>        data[n]=line.rstrip()
> search_keywords='|'.join(data)
> print ('Keywords: ', search_keywords)

Der Code macht aber ein wenig was anders, als was du beschrieben hast. 
Wenn in dein Keyworts.txt eine Zeile mit
line beginnt fügt er dein Code sogar ein Newline ein macht deine Regexp 
mutwillig kaputt. Außerdem entfernt er nicht die Komma, welche du 
zumindest im Beispiel gepostet hast. d.h deine search_keywords für die 
Beispiele sind 'String1,|String2,|String3'

der folgende Code entspricht eher dem was du beschrieben hast erreichen 
zu wollen. beachte bitte das ich 1. jedes Komma entferne und außerdem im 
Vergleich zu dein Code mit den strip statt rstrip auch links vom String 
Leerzeichen entferne.
1
data = list()
2
for line in open('foo.txt').readlines():
3
    line = line.strip()
4
    if not line:
5
       continue
6
    data.append(line.replace(',',''))
7
8
search_keywords = '|'.join(data)
9
print('Keywords: ', search_keywords)

von Joachim S. (oyo)


Lesenswert?

imonbln schrieb:
>>
1
>> if len(line) > 0:
2
>>     if line.startswith('line'):
3
>>
>
> das len(line) > 0 ist in Python nicht nötig
>
>
1
>    if line:
2
>      if line.startswith('line'):
3
>
>
> reicht auch

Stimmt, das macht es noch etwas kürzer.

> Der Code macht aber ein wenig was anders, als was du beschrieben hast.
> Wenn in dein Keyworts.txt eine Zeile mit
> line beginnt fügt er dein Code sogar ein Newline ein macht deine Regexp
> mutwillig kaputt. Außerdem entfernt er nicht die Komma, welche du
> zumindest im Beispiel gepostet hast. d.h deine search_keywords für die
> Beispiele sind 'String1,|String2,|String3'

Dass seine Beschreibung aus den von Dir genannten Gründen nicht 100%ig 
zu seinem Code passt, ist mir auch aufgefallen. Aber da er ja behauptet, 
dass sein Code vom Leerzeilenproblem abgesehen völlig korrekt arbeitet, 
vermute ich ja eher, dass seine Beschreibung einfach verkürzt/ungenau 
war.

Was bspw. der Sinn dahinter sein sollte, dass er in seinem Code 
überprüft, ob eine Zeile mit der Zeichenfolge "line" beginnt, und wenn 
ja dann einen Zeilenumbruch einfügt, hat sich mir z.B. so gar nicht 
erschlossen; aber ich konnte mir partout nicht vorstellen, dass Jemand 
so ein komisches Verhalten explizit einprogrammieren würde, ohne 
irgendetwas damit zu beabsichtigen...

@Threadstarter: Kläre die angesprochenen Merkwürdigkeiten doch mal auf.

von Jason (Gast)


Lesenswert?

Guten Morgen,

danke für die zahlreichen Tipps.

Mein Code sieht momentan wie folgt aus:
1
data = []
2
for line in open('keywords.txt').readlines():
3
    line = line.rstrip()
4
5
6
    if len(line) > 0:
7
        if line.startswith('line'):
8
            line = '\n' + line
9
        if line.startswith('  '):
10
            line = line.strip()
11
12
        line = line.replace(","," ")
13
        line = line.replace(" ","|")
14
        line = line.replace("||","|")
15
16
       
17
                
18
        data.append(line)
19
search_keywords = '|'.join(data)
20
print('Keywords: ', search_keywords)

Die Zeilen  line.replace() habe ich deshalb eingefügt, da die Datei die 
Schlüsselwörter in folgender Form enthalten könnte:

String1 String2
 String1 String2
String1, String2
String 1,String2
String1
String2
String1|String2

Somit wird stets automatisch das Format "String1|String2" ausgegeben und 
es funktioniert, auch wenn auf etwas primitive Art.

von imonbln (Gast)


Lesenswert?

@Threadstarter:

Okay Kommt in deiner Datei das Schlüsselwort 'line' vor ? wenn nicht
ist Dieses Stück Code Toter Code und kann ersatz los entfernt werden.

Jason schrieb:
> if line.startswith('line'):
>             line = '\n' + line

der Code Hier ist sicher auch nicht so Optimal wie du denkst, ich 
übersetze mal, wenn die line mit exat 2 leerzeichen startet entferne 
alle leerzeichen vor und nach dem String.

Jason schrieb:
> if line.startswith('  '):
>             line = line.strip()

ersetz besser die Zeile: line = line.rstrip()
mit line = line.rstrip() und entferne  auch das zweite if ohne wenn und 
aber.

Diese Replace magic:
Jason schrieb:
> line = line.replace(","," ")
> line = line.replace(" ","|")
> line = line.replace("||","|")

Funktioniert im Fall "String 1,String2"? Ich denke hierbei kommt 
"String|1|String2" als regexp raus, ich bin nicht sicher ob du das 
willst.

Generell ist "String 1,String2" mit Abstand der schlechteste Fall für 
dein Code,vielleicht solltest du diesen Fall verbieten und/oder mit 
einer Regexp behandeln. Ausserdem wenn schon mehre Keywords in einer 
Zeile vorkommen mit unterschiedlichen delimetern denk auch hier mal über 
eine Regexp nach
1
import re
2
3
data = list()
4
for line in open('keywords.txt').readlines():
5
    keywords =  re.findall(r"[\w']+", line)
6
    data.extend(keywords)
7
search_keywords = '|'.join(data)
8
print('Keywords: ', search_keywords)

denn fall mit "String 1,String2" handelt der Code nicht aber das Ist 
jetzt deine Aufgabe das zu lösen. Aussdem hat auch der Code nicht den 
Vodoo mit dem Keyword line, ich bin noch nicht überzeugt das du das 
keyword "line" hast.

von Jason (Gast)


Lesenswert?

imonbln schrieb:
> Funktioniert im Fall "String 1,String2"? Ich denke hierbei kommt
> "String|1|String2" als regexp raus, ich bin nicht sicher ob du das
> willst.

Danke dir für die zahlreichen Hilfestellungen. Zum oben zitierten Text, 
bekomme ich das richtige Ergebnis.

von Sheeva P. (sheevaplug)


Lesenswert?

Jason schrieb:
>
1
> data=open("keywords.txt").readlines()
2
> for n,line in enumerate(data):
3
>     if line.startswith("line"):
4
>        data[n] = "\n"+line.rstrip()
5
>     else:
6
>        data[n]=line.rstrip()
7
> search_keywords='|'.join(data)
8
> print ('Keywords: ', search_keywords)
9
>
>
> Es funktioniert auch, aber wenn ich in der Textdatei aus Versehen
> Leerzeilen einfüge, erscheint folgende Ausgabe: String1|String2|String3|
> | |
>
> Dadurch funktioniert der Filter nicht mehr richtig. Gibt es eine
> Möglichkeit, diese Leerzeilen in python zu ignorieren, damit ich eine
> sinnvolle Ausgabe erhalte?
1
search_keywords = '|'.join([d for d in data if d])

oder, alles ganz kurz in einem Rutsch:
1
'|'.join([l.strip() for l in open('f', 'r') if l.strip()])

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.