J'ai un littéral de chaîne multi-lignes que je veux faire une opération sur chaque ligne, comme ceci:
inputString = """Line 1
Line 2
Line 3"""
Je veux faire quelque chose comme ceci:
for line in inputString:
doStuff()
J'ai un littéral de chaîne multi-lignes que je veux faire une opération sur chaque ligne, comme ceci:
inputString = """Line 1
Line 2
Line 3"""
Je veux faire quelque chose comme ceci:
for line in inputString:
doStuff()
Réponses:
inputString.splitlines()
Vous donnera une liste avec chaque élément, la splitlines()
méthode est conçue pour diviser chaque ligne en un élément de liste.
''.splitlines() == []
, pas ['']
comme avec ''.split('\n')
.
Comme les autres l'ont dit:
inputString.split('\n') # --> ['Line 1', 'Line 2', 'Line 3']
Ceci est identique à ce qui précède, mais les fonctions du module de chaîne sont obsolètes et doivent être évitées:
import string
string.split(inputString, '\n') # --> ['Line 1', 'Line 2', 'Line 3']
Alternativement, si vous voulez que chaque ligne inclue la séquence de coupure (CR, LF, CRLF), utilisez la splitlines
méthode avec un True
argument:
inputString.splitlines(True) # --> ['Line 1\n', 'Line 2\n', 'Line 3']
inputString.split(os.linesep)
utilisera le terminateur de ligne spécifique à la plate-forme.
Utilisezstr.splitlines()
.
splitlines()
gère les sauts de ligne correctement, contrairement à split("\n")
.
Il présente également l'avantage mentionné par @efotinis d'inclure éventuellement le caractère de nouvelle ligne dans le résultat de division lorsqu'il est appelé avec un True
argument.
Explication détaillée des raisons pour lesquelles vous ne devez pas utiliser split("\n")
:
\n
, en Python, représente un saut de ligne Unix (code décimal ASCII 10), indépendamment de la plateforme sur laquelle vous l'exécutez. Cependant, la représentation de saut de ligne dépend de la plateforme . Sur Windows, il \n
y a deux caractères CR
et LF
(codes décimaux ASCII 13 et 10, AKA \r
et \n
), tandis que sur tout Unix moderne (y compris OS X), c'est le seul caractère LF
.
print
, par exemple, fonctionne correctement même si vous avez une chaîne dont les fins de ligne ne correspondent pas à votre plate-forme:
>>> print " a \n b \r\n c "
a
b
c
Cependant, un fractionnement explicite sur "\ n" produira un comportement dépendant de la plateforme:
>>> " a \n b \r\n c ".split("\n")
[' a ', ' b \r', ' c ']
Même si vous l'utilisez os.linesep
, il ne se divisera qu'en fonction du séparateur de nouvelle ligne sur votre plate-forme et échouera si vous traitez du texte créé sur d'autres plates-formes, ou avec un nu \n
:
>>> " a \n b \r\n c ".split(os.linesep)
[' a \n b ', ' c ']
splitlines
résout tous ces problèmes:
>>> " a \n b \r\n c ".splitlines()
[' a ', ' b ', ' c ']
La lecture de fichiers en mode texte atténue partiellement le problème de représentation de nouvelle ligne, car il convertit Python \n
en représentation de nouvelle ligne de la plate-forme. Cependant, le mode texte n'existe que sur Windows. Sur les systèmes Unix, tous les fichiers sont ouverts en mode binaire, donc l'utilisation split('\n')
dans un système UNIX avec un fichier Windows entraînera un comportement indésirable. De plus, il n'est pas inhabituel de traiter des chaînes avec des sauts de ligne potentiellement différents à partir d'autres sources, comme à partir d'un socket.
splitlines
se divisera à toute fin de ligne. split(os.linesep)
échouera lors de la lecture d'un fichier Windows sous Unix, par exemple
Peut être exagéré dans ce cas particulier, mais une autre option consiste à utiliser StringIO
pour créer un objet de type fichier
for line in StringIO.StringIO(inputString):
doStuff()
str.split
, n'est pas nécessaire d'allouer de la mémoire (il lit la chaîne en place). Un inconvénient est que c'est beaucoup plus lent si vous utilisezStringIO
(environ 50x). Si vous utilisez cStringIO
, cependant, c'est environ 2x plus rapide
Le message d'origine a demandé du code qui imprime certaines lignes (si elles sont vraies pour certaines conditions) plus la ligne suivante. Ma mise en œuvre serait la suivante:
text = """1 sfasdf
asdfasdf
2 sfasdf
asdfgadfg
1 asfasdf
sdfasdgf
"""
text = text.splitlines()
rows_to_print = {}
for line in range(len(text)):
if text[line][0] == '1':
rows_to_print = rows_to_print | {line, line + 1}
rows_to_print = sorted(list(rows_to_print))
for i in rows_to_print:
print(text[i])
Je souhaite que les commentaires aient un formatage de texte de code approprié, car je pense que la réponse de @ 1_CR a besoin de plus de bosses, et je voudrais augmenter sa réponse. Quoi qu'il en soit, il m'a conduit à la technique suivante; il utilisera cStringIO s'il est disponible (MAIS NOTE: cStringIO et StringIO ne sont pas identiques , car vous ne pouvez pas sous-classer cStringIO ... c'est un intégré ... mais pour les opérations de base la syntaxe sera identique, donc vous pouvez le faire ):
try:
import cStringIO
StringIO = cStringIO
except ImportError:
import StringIO
for line in StringIO.StringIO(variable_with_multiline_string):
pass
print line.strip()