J'aime enregistrer des parties du fichier texte d'origine, qui peuvent être identifiées entre les chaînes «commence par» et «se termine par», dans un nouveau fichier texte.
Exemple: Le fichier texte d'entrée contient les lignes suivantes: p>
with open('file_in.txt','r') as fi:
id = []
for ln in fi:
if ln.startswith("start with string"):
if ln.endswith("ends with string"):
id.append(ln[:])
with open(file_out.txt, 'a', encoding='utf-8') as fo:
fo.write (",".join(id))
print(id)
Je suis intéressé à extraire les lignes suivantes dans le fichier texte de sortie:
starts with string...def...ends with string starts with string...mno...ends with string
Mon code suivant renvoie une liste vide []. Veuillez aider à corriger mon code.
...abc⦠...starts with string... ...def... ...ends with string... ...ghi... ...jkl... ...starts with string... ...mno... ...ends with string... ...pqr...
Je m'attends à ce que le fichier.out.txt contienne, toutes les chaînes commençant par "commencer par la chaîne" et se terminant par "se terminant par chaîne ".
3 Réponses :
commence avec et endswith renvoie Vrai ou Faux plutôt qu'une position que vous pouvez utiliser pour trancher votre chaîne. Essayez find ou index à la place. Par exemple:
start = 'starts with string' end = 'ends with string' s = '...abc⦠...starts with string... ...def... ...ends with string... ...ghi...' sub = s[s.find(start):s.find(end) + len(end)] print(sub) # starts with string... ...def... ...ends with string
Vous devrez ajouter un peu de vérification dans votre boucle pour voir si les chaînes de début et de fin existent car find renverra -1 s'il y a il n'y a pas de correspondance et cela entraînerait un découpage involontaire.
Vous pouvez utiliser une variable distincte pour indiquer si la ligne courante fait partie d'une section intéressante et basculer cette variable en fonction des marqueurs de début et de fin. Ensuite, vous pouvez également transformer cette fonction en générateur:
import itertools as it
def extract(fh, start, stop):
while any(start in x for x in fh):
yield from it.takewhile(lambda x: stop not in x, fh)
with open('test.txt') as fh:
print(''.join(extract(fh, 'starts with string', 'ends with string')))
En Python 3.8, vous pouvez utiliser expressions d'affectation :
import itertools as it
def extract(fh, start, stop):
while any(start in (line := x) for x in fh):
yield line
yield from it.takewhile(lambda x: stop not in x, ((line := y) for y in fh))
yield line
with open('test.txt') as fh:
print(''.join(extract(fh, 'starts with string', 'ends with string')))
En cas de démarrage et d'arrêt les marqueurs doivent être exclus de la sortie, nous pouvons à nouveau utiliser itertools.take While :
def extract(fh, start, stop):
sub = False
for line in fh:
sub |= start in line
if sub:
yield line
sub ^= stop in line
with open('test.txt') as fh:
print(''.join(extract(fh, 'starts with string', 'ends with string')))
@MadPhysicist J'ai mis à jour ma réponse pour répondre aux exigences de l'OP (inclure les marqueurs de démarrage et d'arrêt dans la sortie), également avec un exemple d'utilisation.
@a_guest: Utilisation des 'expressions d'affectation': erreur suivante:> Fichier "
@anatta Comme mentionné, les expressions d'affectation ont été introduites dans Python 3.8 qui n'est actuellement disponible qu'en alpha version .
@a_guest: Je l'ai manqué. Je vais mettre à jour vers la version 3.8 alpha et essayer. Merci.
À la fin de chaque ligne, un caractère indique à l'ordinateur d'afficher une nouvelle ligne. Je suppose ici que "commencer par une chaîne" et "se terminer par une chaîne" sont sur la même ligne. Si ce n'est pas le cas, ajoutez - "id.append (ln [:])" - directement sous la première instruction if.
Essayez
with open('C:\\Py\\testing.txt','r') as fi:
id = []
x = 0
copy_line = False
for ln in fi:
if "starts with string" in ln:
copy_line = True
if copy_line:
id.append ( ln[:] )
if "ends with string" in ln :
copy_line = False
with open ('C:\\Py\\testing_out.txt', 'a', encoding='utf-8' ) as fo:
fo.write (",".join(id))
print(id)
ou
ln.endswith("ends with string"+'\n' +'\r')
ln.endswith("ends with string"+'\n' )
Renvoie toujours une liste vide []. Je vais essayer quelques variantes une mise à jour. Merci.
J'ai une autre stratégie pour utiliser un opérateur booléen. Voir le code mis à jour.
Merci pour la mise à jour avec les données de test. J'ai mis à jour ma réponse en conséquence, veuillez vérifier si elle correspond à vos besoins.