Python中,如何解析字符串看起来像sys.argv中

问题描述:

我想解析字符串是这样的:Python中,如何解析字符串看起来像sys.argv中

-o 1 --long "Some long string" 

到这一点:

["-o", "1", "--long", 'Some long string'] 

或相似。

这是不同于getopt或optparse,其中开始与sys.argv解析的输入(就像我有上面的输出)。有没有一个标准的方法来做到这一点?基本上,这是“分裂”,同时保持引用的字符串在一起。

我迄今为止最好的功能:

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] 
+0

我自己的真正健忘揭示:http://*.com/questions/92533,有我使用shlex.split。显然我只是忘了它。 – 2009-05-25 23:23:03

+0

如果你真正需要的是“处理选项”而不是“在命令行上解析字符串”,你可以考虑http://docs.python.org/2/library/argparse.html – 2013-07-31 12:08:47

我相信你想要的shlex模块。

>>> import shlex 
>>> shlex.split('-o 1 --long "Some long string"') 
['-o', '1', '--long', 'Some long string'] 

我意识到了shlex.split之前,我做了如下:

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)) 

这对Python 2.x和3.x的在Python 2.x中,它直接与字节字符串和Unicode字符串一起工作。在Python 3.x上,它只有接受[Unicode]字符串,而不是bytes对象。

这并不表现完全一样,外壳argv的分裂,这也让CR,LF和制表符的报价为\r\n\t,将它们转换为真正的CR,LF,TAB(shlex.split不会做那)。所以编写我自己的功能对我的需求很有用。我想shlex.split更好,如果你只是想简单的壳式argv分裂。我将分享这些代码,以便它可以用来做一些稍微不同的事情。