python - mutually - sys argv[]
Python, cómo analizar cadenas para que se vean como sys.argv (2)
Antes de shlex.split
cuenta de shlex.split
, hice lo siguiente:
import sys
_WORD_DIVIDERS = set(('' '', ''/t'', ''/r'', ''/n''))
_QUOTE_CHARS_DICT = {
''//': ''//',
'' '': '' '',
''"'': ''"'',
''r'': ''/r'',
''n'': ''/n'',
''t'': ''/t'',
}
def _raise_type_error():
raise TypeError("Bytes must be decoded to Unicode first")
def parse_to_argv_gen(instring):
is_in_quotes = False
instring_iter = iter(instring)
join_string = instring[0:0]
c_list = []
c = '' ''
while True:
# Skip whitespace
try:
while True:
if not isinstance(c, str) and sys.version_info[0] >= 3:
_raise_type_error()
if c not in _WORD_DIVIDERS:
break
c = next(instring_iter)
except StopIteration:
break
# Read word
try:
while True:
if not isinstance(c, str) and sys.version_info[0] >= 3:
_raise_type_error()
if not is_in_quotes and c in _WORD_DIVIDERS:
break
if c == ''"'':
is_in_quotes = not is_in_quotes
c = None
elif c == ''//':
c = next(instring_iter)
c = _QUOTE_CHARS_DICT.get(c)
if c is not None:
c_list.append(c)
c = next(instring_iter)
yield join_string.join(c_list)
c_list = []
except StopIteration:
yield join_string.join(c_list)
break
def parse_to_argv(instring):
return list(parse_to_argv_gen(instring))
Esto funciona con Python 2.xy 3.x. En Python 2.x, funciona directamente con cadenas de bytes y cadenas Unicode. En Python 3.x, solo acepta cadenas [Unicode], no objetos de bytes
.
Esto no se comporta exactamente igual que la división de argv de shell; también permite citar caracteres CR, LF y TAB como /r
, /n
y /t
, convirtiéndolos en CR, LF, TAB shlex.split
( shlex.split
no Haz eso). Así que escribir mi propia función fue útil para mis necesidades. Supongo que shlex.split
es mejor si solo quieres dividir argv estilo shell. Estoy compartiendo este código en caso de que sea útil como línea de base para hacer algo ligeramente diferente.
Me gustaría analizar una cadena como esta:
-o 1 --long "Some long string"
dentro de esto:
["-o", "1", "--long", ''Some long string'']
o similar.
Esto es diferente de getopt u optparse, que comienza con la entrada analizada sys.argv (como la salida que tengo arriba). ¿Hay una manera estándar de hacer esto? Básicamente, esto es "dividir" al mantener unidas las cuerdas entrelazadas.
Mi mejor función hasta el momento:
import csv
def split_quote(string,quotechar=''"''):
''''''
>>> split_quote(''--blah "Some argument" here'')
[''--blah'', ''Some argument'', ''here'']
>>> split_quote("--blah ''Some argument'' here", quotechar="''")
[''--blah'', ''Some argument'', ''here'']
''''''
s = csv.StringIO(string)
C = csv.reader(s, delimiter=" ",quotechar=quotechar)
return list(C)[0]
Creo que quieres el módulo shlex .
>>> import shlex
>>> shlex.split(''-o 1 --long "Some long string"'')
[''-o'', ''1'', ''--long'', ''Some long string'']