Ich habe eine Zeichenfolge, die wie folgt aussieht:
this is "a test"
Ich versuche, etwas in Python zu schreiben, um es nach Leerzeichen aufzuteilen, während Leerzeichen in Anführungszeichen ignoriert werden. Das gesuchte Ergebnis ist:
['this','is','a test']
PS. Ich weiß, dass Sie fragen werden: "Was passiert, wenn die Anführungszeichen Anführungszeichen enthalten? Nun, in meiner Bewerbung wird das niemals passieren."
Antworten:
Sie möchten
split
, aus dem eingebautenshlex
Modul.Dies sollte genau das tun, was Sie wollen.
quelle
shlex.split('this is "a test"', posix=False)
kehrt zurück['this', 'is', '"a test"']
shlex.split()
eineUnicodeEncodeError
Ausnahme auslöst .Schauen Sie sich
shlex
insbesondere das Modul anshlex.split
.quelle
Ich sehe hier Regex-Ansätze, die komplex und / oder falsch aussehen. Dies überrascht mich, da die Regex-Syntax leicht "Leerzeichen oder von Anführungszeichen umgebene Dinge" beschreiben kann und die meisten Regex-Engines (einschließlich Pythons) in einen Regex aufgeteilt werden können. Wenn Sie also reguläre Ausdrücke verwenden möchten, sagen Sie doch einfach genau, was Sie meinen.:
Erläuterung:
shlex bietet jedoch wahrscheinlich mehr Funktionen.
quelle
Abhängig von Ihrem Anwendungsfall möchten Sie möglicherweise auch das
csv
Modul überprüfen :Ausgabe:
quelle
""
), um ein doppeltes Anführungszeichen darzustellen. Daher"
werden zwei doppelte Anführungszeichen in ein einfaches Anführungszeichen umgewandelt'this is "a string""'
und'this is "a string"""'
beide werden['this', 'is', 'a string"']
Ich verwende shlex.split, um 70.000.000 Zeilen Tintenfischprotokoll zu verarbeiten. Es ist so langsam. Also wechselte ich zu re.
Bitte versuchen Sie dies, wenn Sie Leistungsprobleme mit Shlex haben.
quelle
Da diese Frage mit Regex gekennzeichnet ist, habe ich mich für einen Regex-Ansatz entschieden. Ich ersetze zuerst alle Leerzeichen in den Anführungszeichen durch \ x00, teile sie dann durch Leerzeichen und ersetze dann die \ x00 zurück durch Leerzeichen in jedem Teil.
Beide Versionen machen dasselbe, aber Splitter ist etwas besser lesbar als Splitter2.
quelle
Es scheint, dass aus Leistungsgründen
re
schneller ist. Hier ist meine Lösung mit einem am wenigsten gierigen Operator, der die äußeren Anführungszeichen beibehält:Ergebnis:
Es hinterlässt Konstrukte wie
aaa"bla blub"bbb
zusammen, da diese Token nicht durch Leerzeichen getrennt sind. Wenn die Zeichenfolge maskierte Zeichen enthält, können Sie wie folgt übereinstimmen:Bitte beachten Sie, dass dies auch mit der leeren Zeichenfolge
""
über den\S
Teil des Musters übereinstimmt .quelle
,
via'(?:".*?"|[^,])+'
). Gleiches gilt für die Anführungszeichen.Das Hauptproblem bei dem akzeptierten
shlex
Ansatz besteht darin, dass Escape-Zeichen außerhalb von Anführungszeichen in Anführungszeichen nicht ignoriert werden und in einigen Eckfällen leicht unerwartete Ergebnisse erzielt werden.Ich habe den folgenden Anwendungsfall, in dem ich eine Teilungsfunktion benötige, die Eingabezeichenfolgen so aufteilt, dass entweder einfache oder doppelte Anführungszeichen erhalten bleiben, wobei Anführungszeichen innerhalb einer solchen Teilzeichenfolge vermieden werden können. Anführungszeichen in einer Zeichenfolge ohne Anführungszeichen sollten nicht anders behandelt werden als andere Zeichen. Einige Beispieltestfälle mit der erwarteten Ausgabe:
Am Ende hatte ich die folgende Funktion, um eine Zeichenfolge so aufzuteilen, dass die erwartete Ausgabe für alle Eingabezeichenfolgen resultiert:
Die folgende Testanwendung überprüft die Ergebnisse anderer Ansätze (
shlex
undcsv
vorerst) und der benutzerdefinierten Split-Implementierung:Ausgabe:
Die Leistung ist also viel besser als
shlex
und kann durch Vorkompilieren des regulären Ausdrucks weiter verbessert werden. In diesem Fall wird dercsv
Ansatz übertroffen .quelle
shlex
sich meine Anwendungsfälle nicht wie erwartet verhalten.Verwenden Sie diese Funktion, um Anführungszeichen beizubehalten:
quelle
Geschwindigkeitstest verschiedener Antworten:
quelle
Hmm, ich kann den "Antworten" -Button anscheinend nicht finden ... diese Antwort basiert auf dem Ansatz von Kate, teilt jedoch Zeichenfolgen korrekt mit Teilzeichenfolgen, die maskierte Anführungszeichen enthalten, und entfernt auch die Start- und Endanführungszeichen der Teilzeichenfolgen:
Dies funktioniert mit Strings wie
'This is " a \\\"test\\\"\\\'s substring"'
(das verrückte Markup ist leider notwendig, um Python davon abzuhalten, die Escapezeichen zu entfernen).Wenn die resultierenden Escapezeichen in den Zeichenfolgen in der zurückgegebenen Liste nicht erwünscht sind, können Sie diese leicht geänderte Version der Funktion verwenden:
quelle
Um die Unicode-Probleme in einigen Python 2-Versionen zu umgehen, schlage ich vor:
quelle
split = lambda a: [b.decode('utf-8') for b in _split(a)]
Andernfalls erhalten Sie:UnicodeDecodeError: 'ascii' codec can't decode byte ... in position ...: ordinal not in range(128)
Als Option versuchen Sie tssplit:
quelle
Ich schlage vor:
Testzeichenfolge:
auch "" und '' erfassen:
Ergebnis:
leere "" und '' zu ignorieren:
Ergebnis:
quelle
re.findall("(?:\".*?\"|'.*?'|[^\s'\"]+)", s)
auch geschrieben werden .Wenn Sie sich nicht für Unterzeichenfolgen interessieren, dann für eine einfache
Performance:
Oder String-Modul
Leistung: Das String-Modul scheint eine bessere Leistung zu erzielen als String-Methoden
Oder Sie können die RE-Engine verwenden
Performance
Bei sehr langen Zeichenfolgen sollten Sie nicht die gesamte Zeichenfolge in den Speicher laden und stattdessen entweder die Zeilen teilen oder eine iterative Schleife verwenden
quelle
Versuche dies:
Einige Testzeichenfolgen:
quelle
adamsplit("This is 'a test'")
→['This', 'is', "'a", "test'"]