如何像python中的shell一样将字符串拆分为命令行参数?
我在字符串中有命令行参数,我需要将其拆分以提供给 argparse.ArgumentParser.parse_args
.
I have command line arguments in a string and I need to split it to feed to argparse.ArgumentParser.parse_args
.
我看到 文档 使用 string.split()
很多.但是在复杂的情况下,这不起作用,例如
I see that the documentation uses string.split()
plentifully. However in complex cases, this does not work, such as
--foo "spaces in brakets" --bar escaped\ spaces
python 中是否有这样的功能?
Is there a functionality to do that in python?
(在here).
如果您正在解析 Windows 样式的命令行,则 shlex.split
无法正常工作 - 调用 对结果的 subprocess
函数与将字符串直接传递给 shell 的行为不同.
If you're parsing a windows-style command line, then shlex.split
doesn't work correctly - calling subprocess
functions on the result will not have the same behavior as passing the string directly to the shell.
在那种情况下,将像命令行参数这样的字符串拆分给 python 的最可靠方法是……将命令行参数传递给 python:
In that case, the most reliable way to split a string like the command-line arguments to python is... to pass command line arguments to 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"']