shlex — Einfache lexikalische Analyse¶
Quellcode: Lib/shlex.py
Die Klasse shlex erleichtert das Schreiben von lexikalischen Analysatoren für einfache Syntaxen, die der Unix-Shell ähneln. Dies ist oft nützlich für das Schreiben von Minisprachen (z. B. in Konfigurationsdateien für Python-Anwendungen) oder zum Parsen von Anführungszeichen-Strings.
Das Modul shlex definiert die folgenden Funktionen
- shlex.split(s, comments=False, posix=True)¶
Teilt den String s unter Verwendung einer Shell-ähnlichen Syntax. Wenn comments
False(Standard) ist, ist die Analyse von Kommentaren im gegebenen String deaktiviert (das Attributcommentersdershlex-Instanz wird auf einen leeren String gesetzt). Diese Funktion arbeitet standardmäßig im POSIX-Modus, verwendet jedoch den Nicht-POSIX-Modus, wenn das Argument posix falsch ist.Geändert in Version 3.12: Das Übergeben von
Nonefür das Argument s löst nun eine Ausnahme aus, anstatt vonsys.stdinzu lesen.
- shlex.join(split_command)¶
Verkettet die Token der Liste split_command und gibt einen String zurück. Diese Funktion ist die Umkehrung von
split().>>> from shlex import join >>> print(join(['echo', '-n', 'Multiple words'])) echo -n 'Multiple words'
Der zurückgegebene Wert ist Shell-escaped, um Injection-Schwachstellen zu vermeiden (siehe
quote()).Hinzugefügt in Version 3.8.
- shlex.quote(s)¶
Gibt eine Shell-escaped Version des Strings s zurück. Der zurückgegebene Wert ist ein String, der sicher als ein einzelnes Token in einer Shell-Befehlszeile verwendet werden kann, für Fälle, in denen Sie keine Liste verwenden können.
Warnung
Das Modul
shlexist nur für Unix-Shells konzipiert.Die Funktion
quote()ist nicht garantiert korrekt für nicht-POSIX-konforme Shells oder Shells anderer Betriebssysteme wie Windows. Die Ausführung von mit diesem Modul gequoteten Befehlen auf solchen Shells kann zu Command-Injection-Schwachstellen führen.Erwägen Sie die Verwendung von Funktionen, die Befehlsargumente als Listen übergeben, wie z. B.
subprocess.run()mitshell=False.Dieses Idiom wäre unsicher
>>> filename = 'somefile; rm -rf ~' >>> command = 'ls -l {}'.format(filename) >>> print(command) # executed by a shell: boom! ls -l somefile; rm -rf ~
quote()schließt die Sicherheitslücke>>> from shlex import quote >>> command = 'ls -l {}'.format(quote(filename)) >>> print(command) ls -l 'somefile; rm -rf ~' >>> remote_command = 'ssh home {}'.format(quote(command)) >>> print(remote_command) ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''
Die Quoting ist kompatibel mit UNIX-Shells und mit
split()>>> from shlex import split >>> remote_command = split(remote_command) >>> remote_command ['ssh', 'home', "ls -l 'somefile; rm -rf ~'"] >>> command = split(remote_command[-1]) >>> command ['ls', '-l', 'somefile; rm -rf ~']
Hinzugefügt in Version 3.3.
Das Modul shlex definiert die folgende Klasse
- class shlex.shlex(instream=None, infile=None, posix=False, punctuation_chars=False)¶
Eine Instanz von
shlexoder eine Instanz einer Unterklasse ist ein lexikalisches Analyseobjekt. Das Initialisierungsargument gibt, falls vorhanden, an, woher Zeichen gelesen werden sollen. Es muss ein datei-/stream-ähnliches Objekt mit Methodenread()undreadline()oder ein String sein. Wenn kein Argument angegeben wird, werden Eingaben vonsys.stdingelesen. Das zweite optionale Argument ist ein Dateiname-String, der den Anfangswert des Attributsinfilesetzt. Wenn das Argument instream weggelassen wird oder gleichsys.stdinist, ist dieses zweite Argument standardmäßig „stdin“. Das Argument posix definiert den Betriebsmodus: Wenn posix nicht wahr ist (Standard), arbeitet dieshlex-Instanz im Kompatibilitätsmodus. Im POSIX-Modus versuchtshlex, so nah wie möglich an den POSIX-Shell-Parsing-Regeln zu sein. Das Argument punctuation_chars bietet eine Möglichkeit, das Verhalten noch näher an die Art und Weise anzupassen, wie echte Shells parsen. Dies kann eine Reihe von Werten annehmen: Der StandardwertFalsebehält das Verhalten bei, das unter Python 3.5 und früheren Versionen zu sehen war. Wenn es aufTruegesetzt wird, ändert sich die Analyse der Zeichen();<>|&: Jeder Lauf dieser Zeichen (als Satzzeichen betrachtet) wird als einzelnes Token zurückgegeben. Wenn es auf einen nicht leeren String von Zeichen gesetzt wird, werden diese Zeichen als Satzzeichen verwendet. Zeichen im Attributwordchars, die in punctuation_chars vorkommen, werden auswordcharsentfernt. Siehe Verbesserte Kompatibilität mit Shells für weitere Informationen. punctuation_chars kann nur bei der Erstellung einershlex-Instanz gesetzt und später nicht mehr geändert werden.Geändert in Version 3.6: Der Parameter punctuation_chars wurde hinzugefügt.
Siehe auch
- Modul
configparser Parser für Konfigurationsdateien ähnlich den Windows
.ini-Dateien.
shlex-Objekte¶
Eine Instanz von shlex hat die folgenden Methoden
- shlex.get_token()¶
Gibt ein Token zurück. Wenn Tokens mit
push_token()gestapelt wurden, wird ein Token vom Stapel genommen. Andernfalls wird eines aus dem Eingabestream gelesen. Wenn das Lesen auf ein sofortiges Dateiende stößt, wirdeofzurückgegeben (der leere String ('') im Nicht-POSIX-Modus undNoneim POSIX-Modus).
- shlex.push_token(str)¶
Legt das Argument auf den Token-Stapel.
- shlex.read_token()¶
Liest ein rohes Token. Ignoriert den Rückschiebestapel und interpretiert keine Quellenanfragen. (Dies ist normalerweise kein nützlicher Einstiegspunkt und wird hier nur der Vollständigkeit halber dokumentiert.)
- shlex.sourcehook(filename)¶
Wenn
shlexeine Quellenanfrage erkennt (siehesourceunten), wird diese Methode mit dem folgenden Token als Argument aufgerufen und soll ein Tupel zurückgeben, das aus einem Dateinamen und einem geöffneten dateiähnlichen Objekt besteht.Normalerweise entfernt diese Methode zuerst alle Anführungszeichen vom Argument. Wenn das Ergebnis ein absoluter Pfadname ist, oder keine vorherige Quellenanfrage in Kraft war, oder die vorherige Quelle ein Stream war (wie z. B.
sys.stdin), bleibt das Ergebnis unverändert. Andernfalls, wenn das Ergebnis ein relativer Pfadname ist, wird der Verzeichnisteil des Namens der Datei, die ihm unmittelbar auf dem Stapel der Quellcode-Einbindung folgt, vorangestellt (dieses Verhalten ähnelt der Art und Weise, wie der C-Präprozessor#include "file.h"behandelt).Das Ergebnis der Manipulationen wird als Dateiname behandelt und als erste Komponente des Tupels zurückgegeben, wobei
open()darauf aufgerufen wird, um die zweite Komponente zu liefern. (Hinweis: dies ist die umgekehrte Reihenfolge der Argumente bei der Instanzinitialisierung!)Dieser Hook wird bereitgestellt, damit Sie ihn zur Implementierung von Verzeichnissuchpfaden, zum Hinzufügen von Dateierweiterungen und anderen Namespace-Hacks verwenden können. Es gibt keinen entsprechenden ‚close‘-Hook, aber eine shlex-Instanz ruft die Methode
close()des gelesenen Eingabestroms auf, wenn er EOF zurückgibt.Für eine explizitere Steuerung der Quellcode-Einbindung verwenden Sie die Methoden
push_source()undpop_source().
- shlex.push_source(newstream, newfile=None)¶
Fügt einen Eingabequellen-Stream auf den Eingabestapel auf. Wenn das Dateiname-Argument angegeben wird, ist es später für die Verwendung in Fehlermeldungen verfügbar. Dies ist dieselbe Methode, die intern von der Methode
sourcehook()verwendet wird.
- shlex.pop_source()¶
Nimmt die zuletzt hinzugefügte Eingabequelle vom Eingabestapel. Dies ist dieselbe Methode, die intern verwendet wird, wenn der Lexer das EOF auf einem gestapelten Eingabestrom erreicht.
- shlex.error_leader(infile=None, lineno=None)¶
Diese Methode generiert eine Fehlermeldungs-Überschrift im Format eines Unix C-Compiler-Fehleretiketts; das Format ist
'"%s", line %d: ', wobei%sdurch den Namen der aktuellen Quelldatei und%ddurch die aktuelle Eingabezeilennummer ersetzt wird (die optionalen Argumente können verwendet werden, um diese zu überschreiben).Diese Annehmlichkeit wird bereitgestellt, um Benutzer von
shlexzu ermutigen, Fehlermeldungen im standardmäßigen, parsierbaren Format zu generieren, das von Emacs und anderen Unix-Tools verstanden wird.
Instanzen von Unterklassen von shlex haben einige öffentliche Instanzvariablen, die entweder die lexikalische Analyse steuern oder zum Debuggen verwendet werden können
- shlex.commenters¶
Der String von Zeichen, die als Kommentar-Beginn erkannt werden. Alle Zeichen vom Kommentar-Beginn bis zum Zeilenende werden ignoriert. Enthält standardmäßig nur
'#'.
- shlex.wordchars¶
Der String von Zeichen, die sich zu mehrzeichenigen Tokens ansammeln. Standardmäßig sind dies alle ASCII-Alphanumerika und Unterstriche. Im POSIX-Modus sind auch die akzentuierten Zeichen des Latin-1-Zeichensatzes enthalten. Wenn
punctuation_charsnicht leer ist, werden die Zeichen~-./*?=, die in Dateinamen-Spezifikationen und Kommandozeilenparametern vorkommen können, ebenfalls in dieses Attribut aufgenommen, und alle Zeichen, die inpunctuation_charsvorkommen, werden auswordcharsentfernt, wenn sie dort vorhanden sind. Wennwhitespace_splitaufTruegesetzt ist, hat dies keine Auswirkung.
- shlex.whitespace¶
Zeichen, die als Leerzeichen betrachtet und übersprungen werden. Leerzeichen begrenzen Tokens. Standardmäßig sind dies Leerzeichen, Tabulator, Zeilenvorschub und Wagenrücklauf.
- shlex.escape¶
Zeichen, die als Escape-Zeichen betrachtet werden. Dies wird nur im POSIX-Modus verwendet und enthält standardmäßig nur
'\'.
- shlex.quotes¶
Zeichen, die als Anführungszeichen betrachtet werden. Das Token sammelt sich an, bis dasselbe Anführungszeichen erneut angetroffen wird (somit schützen verschiedene Anführungszeichen-Typen einander wie in der Shell). Standardmäßig sind dies ASCII-Einzel- und Doppelanführungszeichen.
- shlex.escapedquotes¶
Zeichen in
quotes, die Escape-Zeichen interpretieren, die inescapedefiniert sind. Dies wird nur im POSIX-Modus verwendet und enthält standardmäßig nur'"'.
- shlex.whitespace_split¶
Wenn
True, werden Tokens nur durch Leerzeichen getrennt. Dies ist nützlich, z. B. zum Parsen von Kommandozeilen mitshlex, um Tokens ähnlich wie Shell-Argumente zu erhalten. Bei Verwendung in Kombination mitpunctuation_charswerden Tokens zusätzlich zu diesen Zeichen durch Leerzeichen getrennt.Geändert in Version 3.8: Das Attribut
punctuation_charswurde mit dem Attributwhitespace_splitkompatibel gemacht.
- shlex.infile¶
Der Name der aktuellen Eingabedatei, wie er bei der Instanziierung der Klasse festgelegt oder durch spätere Quellenanfragen gestapelt wurde. Es kann nützlich sein, dies bei der Erstellung von Fehlermeldungen zu untersuchen.
- shlex.source¶
Dieses Attribut ist standardmäßig
None. Wenn Sie ihm einen String zuweisen, wird dieser String als eine lexikalische Einbindungsanfrage erkannt, ähnlich dem Schlüsselwortsourcein verschiedenen Shells. Das bedeutet, dass das unmittelbar folgende Token als Dateiname geöffnet wird und von diesem Stream bis zum EOF gelesen wird, woraufhin die Methodeclose()dieses Streams aufgerufen wird und die Eingabequelle wieder der ursprüngliche Eingabestream wird. Quellenanfragen können beliebig tief gestapelt werden.
- shlex.debug¶
Wenn dieses Attribut numerisch und
1oder größer ist, gibt eineshlex-Instanz detaillierte Fortschrittsausgaben über ihr Verhalten aus. Wenn Sie dies verwenden müssen, können Sie den Modulquellcode lesen, um die Details zu erfahren.
- shlex.lineno¶
Quellzeilennummer (Anzahl der bisher gesehenen Zeilenumbrüche plus eins).
- shlex.token¶
Der Token-Puffer. Es kann nützlich sein, dies beim Abfangen von Ausnahmen zu untersuchen.
- shlex.eof¶
Token, das zur Bestimmung des Dateiendes verwendet wird. Dies wird auf den leeren String (
'') im Nicht-POSIX-Modus und aufNoneim POSIX-Modus gesetzt.
- shlex.punctuation_chars¶
Eine schreibgeschützte Eigenschaft. Zeichen, die als Satzzeichen betrachtet werden. Läufe von Satzzeichen werden als einzelnes Token zurückgegeben. Beachten Sie jedoch, dass keine semantische Gültigkeitsprüfung durchgeführt wird: Zum Beispiel kann „>>>“ als Token zurückgegeben werden, auch wenn es von Shells möglicherweise nicht als solches erkannt wird.
Hinzugefügt in Version 3.6.
Parsing-Regeln¶
Im Nicht-POSIX-Modus versucht shlex, die folgenden Regeln zu befolgen.
Anführungszeichen werden innerhalb von Wörtern nicht erkannt (
Do"Not"Separatewird als einzelnes WortDo"Not"Separategeparst);Escape-Zeichen werden nicht erkannt;
Das Umschließen von Zeichen in Anführungszeichen bewahrt den literalen Wert aller Zeichen innerhalb der Anführungszeichen;
Schließende Anführungszeichen trennen Wörter (
"Do"Separatewird als"Do"undSeparategeparst);Wenn
whitespace_splitFalseist, wird jedes Zeichen, das nicht als Wortzeichen, Leerzeichen oder Anführungszeichen deklariert ist, als einzelnes Zeichen-Token zurückgegeben. Wenn esTrueist, trenntshlexWörter nur durch Leerzeichen;EOF wird durch einen leeren String (
'') signalisiert;Es ist nicht möglich, leere Strings zu parsen, auch wenn sie zitiert sind.
Im POSIX-Modus versucht shlex, die folgenden Parsing-Regeln zu befolgen.
Anführungszeichen werden entfernt und trennen keine Wörter (
"Do"Not"Separate"wird als einzelnes WortDoNotSeparategeparst);Nicht zitierte Escape-Zeichen (z. B.
'\') bewahren den literalen Wert des nächsten Zeichens, das folgt;Das Umschließen von Zeichen in Anführungszeichen, die nicht Teil von
escapedquotessind (z. B."'"), bewahrt den literalen Wert aller Zeichen innerhalb der Anführungszeichen;Das Umschließen von Zeichen in Anführungszeichen, die Teil von
escapedquotessind (z. B.'"'), bewahrt den literalen Wert aller Zeichen innerhalb der Anführungszeichen, mit Ausnahme der inescapegenannten Zeichen. Die Escape-Zeichen behalten ihre spezielle Bedeutung nur, wenn sie vom verwendeten Anführungszeichen oder dem Escape-Zeichen selbst gefolgt werden. Andernfalls wird das Escape-Zeichen als normales Zeichen behandelt.EOF wird mit einem
None-Wert signalisiert;Anführungszeichen um leere Strings (
'') sind erlaubt.
Verbesserte Kompatibilität mit Shells¶
Hinzugefügt in Version 3.6.
Die Klasse shlex bietet Kompatibilität mit dem Parsen, das von gängigen Unix-Shells wie bash, dash und sh durchgeführt wird. Um diese Kompatibilität zu nutzen, geben Sie das Argument punctuation_chars im Konstruktor an. Dieses ist standardmäßig auf False gesetzt, was das Verhalten vor 3.6 beibehält. Wenn es jedoch auf True gesetzt wird, ändert sich das Parsen der Zeichen ();<>|&: Jede Sequenz dieser Zeichen wird als ein einzelnes Token zurückgegeben. Obwohl dies noch kein vollständiger Parser für Shells ist (was angesichts der Vielfalt an Shells den Rahmen der Standardbibliothek sprengen würde), ermöglicht es Ihnen, Befehlszeilen einfacher zu verarbeiten als bisher. Zur Veranschaulichung sehen Sie den Unterschied im folgenden Ausschnitt
>>> import shlex
>>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"
>>> s = shlex.shlex(text, posix=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']
>>> s = shlex.shlex(text, posix=True, punctuation_chars=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',
'(', 'def', 'ghi', ')']
Natürlich werden auch Tokens zurückgegeben, die für Shells nicht gültig sind, und Sie müssen Ihre eigenen Fehlerprüfungen für die zurückgegebenen Tokens implementieren.
Anstatt True als Wert für den Parameter punctuation_chars zu übergeben, können Sie einen String mit bestimmten Zeichen übergeben, der bestimmt, welche Zeichen als Satzzeichen gelten. Zum Beispiel
>>> import shlex
>>> s = shlex.shlex("a && b || c", punctuation_chars="|")
>>> list(s)
['a', '&', '&', 'b', '||', 'c']
Hinweis
Wenn punctuation_chars angegeben ist, wird das Attribut wordchars mit den Zeichen ~-./*?= erweitert. Dies liegt daran, dass diese Zeichen in Dateinamen (einschließlich Wildcards) und Kommandozeilenargumenten (z. B. --color=auto) vorkommen können. Daher
>>> import shlex
>>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
... punctuation_chars=True)
>>> list(s)
['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']
Um der Shell jedoch so nahe wie möglich zu kommen, wird empfohlen, immer posix und whitespace_split zu verwenden, wenn punctuation_chars verwendet wird, was wordchars vollständig negiert.
Für die beste Wirkung sollte punctuation_chars zusammen mit posix=True gesetzt werden. (Beachten Sie, dass posix=False der Standard für shlex ist.)