2017-07-06 2 views
1

Ich habe Befehlszeilenargumente in einer Zeichenfolge und ich muss es teilen, um an argparse.ArgumentParser.parse_args zu füttern.Wie teilt man einen String wie die Shell in Python?

Ich sehe, dass the documentation verwendet string.split() reichlich. In komplexen Fällen funktioniert dies jedoch nicht, z. B.

Gibt es eine Funktion, die in Python zu tun?

(Eine ähnliche Frage wurde für java gestellt here).

+0

was sollte die Ausgabe genau von 'argparse.ArgumentParser.parse_args' sein –

+0

Sie müssen uns ein vollständiges Programm zeigen, das das spezifische Problem zeigt, das Sie haben, mit Beispieleingabe, die es auslöst. –

Antwort

8
+0

Schön! Und es ist seit Python 2.3 verfügbar. – randomir

+0

Hat 'shlex.split' ein Problem mit gestrichenen Anführungszeichen? zB '--foo" bar \ "baz \" " – user1735003

+0

@ user1735003: Ja, obwohl es normalerweise die Shell sein würde, die das für dich handhabt (' shlex' folgt meistens denselben Regeln wie 'sh' Shell-Regeln). Aber wenn du es getan hast eine konstruierte Befehlszeile wie diese, es ist in Ordnung, das ist der ganze Sinn von 'shlex':' shlex.split (r '- foo "bar \" baz' ') 'produziert' [' --foo ',' bar "baz ']'. Die 'argparse'-Dokumente sind [faul] (https://bugs.python.org/issue20598), wenn sie' str.split' anstelle von 'shlex.split' (oder explizite Listen) verwenden. Sie gingen nur kurz, aber ohne die mentale Belastung, die sie benötigten. – ShadowRanger

0

Sie konnten die split_arg_string Helferfunktion vom click Paket verwenden:

import re 

def split_arg_string(string): 
    """Given an argument string this attempts to split it into small parts.""" 
    rv = [] 
    for match in re.finditer(r"('([^'\\]*(?:\\.[^'\\]*)*)'" 
          r'|"([^"\\]*(?:\\.[^"\\]*)*)"' 
          r'|\S+)\s*', string, re.S): 
     arg = match.group().strip() 
     if arg[:1] == arg[-1:] and arg[:1] in '"\'': 
      arg = arg[1:-1].encode('ascii', 'backslashreplace') \ 
       .decode('unicode-escape') 
     try: 
      arg = type(string)(arg) 
     except UnicodeError: 
      pass 
     rv.append(arg) 
    return rv 

Zum Beispiel:

>>> print split_arg_string('"this is a test" 1 2 "1 \\" 2"') 
['this is a test', '1', '2', '1 " 2'] 

Das click Paket beginnt für Kommando Argumente zu dominieren Parsen, aber ich don‘ Ich denke, es unterstützt Parsen von Argumenten aus String (nur von argv). Die obige Hilfsfunktion wird nur für die bash Vervollständigung verwendet.

Bearbeiten: Ich kann nur empfehlen, die shlex.split() zu verwenden, wie in der Antwort von @ShadowRanger vorgeschlagen. Der einzige Grund, warum ich diese Antwort nicht lösche, ist, dass sie ein bisschen schneller spaltet dann der vollwertige pure-python Tokenizer in shlex (etwa 3.5x schneller für das obige Beispiel, 5.9us vs 20.5us) verwendet. Dies sollte jedoch kein Grund sein, es über shlex zu bevorzugen.

Verwandte Themen