8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何将字符串拆分为类似 python 中的 shell 的命令行参数?

Dpedrinha 2月前

56 0

我在字符串中含有命令行参数,我需要将其拆分以提供给 argparse.ArgumentParser.parse_args。我看到文档大量使用了 string.split()。然而在复杂情况下...

我在字符串中有一个命令行参数,我需要将其拆分以提供给 argparse.ArgumentParser.parse_args .

我看到 文档中 用法 string.split() 。然而在复杂的情况下,这不起作用,例如

--foo "spaces in brakets"  --bar escaped\ spaces

在 python 中是否有可以实现该功能的功能?

A similar question for java was asked here )。

帖子版权声明 1、本帖标题:如何将字符串拆分为类似 python 中的 shell 的命令行参数?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Dpedrinha在本站《regex》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 您需要向我们展示一个完整的程序,以说明您遇到的具体问题,并提供触发该问题的示例输入。

  • 如果您正在解析 Windows 风格的命令行,则 shlex.split 无法正常工作 - subprocess 对结果调用函数将不会具有与将字符串直接传递给 shell 相同的行为。

    在这种情况下,像 python 的命令行参数那样拆分字符串的最可靠方法是......将命令行参数传递给 python:

    import sys
    import subprocess
    import shlex
    import json  # json is an easy way to send arbitrary ascii-safe lists of strings out of python
    
    def shell_split(cmd):
        """
        Like `shlex.split`, but uses the Windows splitting syntax when run on Windows.
    
        On windows, this is the inverse of subprocess.list2cmdline
        """
        if os.name == 'posix':
            return shlex.split(cmd)
        else:
            # TODO: write a version of this that doesn't invoke a subprocess
            if not cmd:
                return []
            full_cmd = '{} {}'.format(
                subprocess.list2cmdline([
                    sys.executable, '-c',
                    'import sys, json; print(json.dumps(sys.argv[1:]))'
                ]), cmd
            )
            ret = subprocess.check_output(full_cmd).decode()
            return json.loads(ret)
    

    举一个它们有何不同的例子:

    # windows does not treat all backslashes as escapes
    >>> shell_split(r'C:\Users\me\some_file.txt "file with spaces"', 'file with spaces')
    ['C:\\Users\\me\\some_file.txt', 'file with spaces']
    
    # posix does
    >>> shlex.split(r'C:\Users\me\some_file.txt "file with spaces"')
    ['C:Usersmesome_file.txt', 'file with spaces']
    
    # non-posix does not mean Windows - this produces extra quotes
    >>> shlex.split(r'C:\Users\me\some_file.txt "file with spaces"', posix=False)
    ['C:\\Users\\me\\some_file.txt', '"file with spaces"']  
    
  • shlex.split 是否存在转义引号的问题?例如 --foo \'bar\\'baz\'

  • @user1735003:是的,尽管通常是 shell 为您处理这个问题(shlex 遵循的规则与 sh shell 规则基本相同)。但是如果您有这样的构造命令行,那就没问题了,这就是 shlex 的重点:shlex.split(r'--foo \'bar\\'baz\'') 生成 ['--foo', 'bar\'baz']。argparse 文档在使用 str.split 而不是 shlex.split(或显式列表)时很懒惰;他们追求简洁,但不需要 shlex 知识的心理负担。

  • @Eric:鉴于没有单一的 Windows 格式(Windows 可执行文件接收原始字符串并自行解析),并且问题是关于解析字符串以供 argparse 处理(无论操作系统如何都有固定的行为),您的评论似乎与这种情况没有特别的关系。

  • 尽管 Windows 接收原始字符串,但大多数程序都会定义 main(argc, argv),最终使用其 C 运行时提供的解析。argparse 具有固定的行为,无论操作系统如何,但这是因为它将字符串列表作为输入,通常是 sys.argv。sys.argv 的填充方式取决于平台,值得注意。shlex.split 与 posix 系统上 sys.argv 的填充方式匹配,但与 windows 系统上 sys.argv 的填充方式不匹配。

  • 您可以使用 click 中的 click

    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
    

    例如:

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

    click 包开始在命令参数解析方面占据主导地位,但我认为它不支持从字符串解析参数(仅从 argv )。上面的辅助函数仅用于 bash 完成。

    编辑 :我只能推荐使用 @ShadowRanger 的答案中所建议的 shlex.split() 比使用的完整纯 Python 标记器 更快的拆分速度 shlex (对于上面的示例,速度大约快 3.5 倍,5.9us vs 20.5us)。然而,这不应该成为更喜欢它的理由 shlex .

返回
作者最近主题: