我正在尝试找到最恐怖的方式来获取包含命令行选项的字符串:
"-t 500 -x -c 3 -d"
将其变成字典
{"-t":"500", "-x":True, "-c":"3", "-d": True}
更新:该字符串还应该能够包含--long选项,以及中间带有破折号的字词:
"-t 500 -x -c 3 -d --long-option 456 -testing weird-behaviour"
在建议我查看OptionParse模块之前,请记住我不知道有效选项是什么或类似的东西,我只是想把字符串放到字典中以允许根据不同的字典修改它选项。
我正在考虑的方法是使用split()将项目放入列表中,然后遍历列表并查找以短划线“ - ”开头的项目并将其用作键,然后以某种方式进入值列表中的下一个项目。我遇到的问题是没有值的选项。我想做类似的事情:
for i in range(0, len(opt_list)):
if opt_list[i][0] == "-":
if len(opt_list) > i+1 and not opt_list[i+1][0] == "-":
opt_dict[opt_list[i]] = opt_list[i+1]
else:
opt_dict[opt_list[i]] = True
但是,当我这样做时,我似乎用C编程而不是Python ...
答案 0 :(得分:6)
要正确处理引号内的空格,可以使用shlex.split()
:
import shlex
cmdln_args = ('-t 500 -x -c 3 -d --long-option 456 '
'-testing "weird -behaviour" -m "--inside"')
args = shlex.split(cmdln_args)
options = {k: True if v.startswith('-') else v
for k,v in zip(args, args[1:]+["--"]) if k.startswith('-')}
from pprint import pprint
pprint(options)
{'--inside': True,
'--long-option': '456',
'-c': '3',
'-d': True,
'-m': True,
'-t': '500',
'-testing': 'weird -behaviour',
'-x': True}
答案 1 :(得分:3)
你可以像这样使用正则表达式:
import re
args = "-t 500 -x -c 3 -d --long-option 456 -testing weird-behaviour"
matches = re.findall(r'(--?[\w-]+)(.*?)(?= -|$)', args)
result = {}
for match in matches:
result[match[0]] = True if not match[1] else match[1].strip()
print result
,结果等于
{
'-d': True,
'-c': '3',
'-t': '500',
'--long-option': '456',
'-x': True,
'-testing': 'weird-behaviour'
}
正则表达式细分:
(--?[\w-]+)(.*?)(?= -|$)
(--?[\w-]+)
匹配以“ - ”或“ - ”开头的任何字符或单词(单词中允许的短划线)。(.*?)
使用问号在non-greedy or minimal fashion中对任意字符进行0次或多次匹配。(?= -|$)
是一个积极的向前看。它会检查我们要查找的内容后跟一个“ - ”或字符串的结尾,但它不会在匹配中包含它。请注意在此正则表达式中使用括号。这些用于创建组,因此当我们调用findall
时,它会将它们分成元组。
答案 2 :(得分:2)
人类的争论解析 - https://github.com/kennethreitz/args
答案 3 :(得分:1)
我不能用最Pythonic
的方式说话,但这里有一个单行:
opt_list = "-t 500 -x -c 3 -d"
dict((e if len(e) >1 else (e[0],True) for e in (elem.split()
for elem in ('-'+d for d in opt_list.split('-') if d))))
>>>{'-t': '500', '-x': True, '-c': '3', '-d': True}
[编辑:正如马蒂亚斯指出的那样,这对于其中带有“ - ”的值不起作用]
...但是,一般来说,当你在选项值中允许' - '时,我认为OP的答案不能毫无疑问地解决。
考虑以下简单选项:
“ - a -b”
这是:
???
答案 4 :(得分:0)
>>> results = "-t 500 -x -c 3 -d".split()
>>> rd = {}
>>> while i < len(results):
... if results[i].startswith("-"):
... rd[results[i]]=True
... try:
... if not results[i+1].startswith("-"):
... rd[results[i]] = results[i+1]
... except IndexError: pass
... i+=1
...
>>> rd
{'-t': '500', '-x': True, '-c': '3', '-d': True}
但与你的相似......
答案 5 :(得分:0)
它最初出现的一个更难的问题,这是我的第一次尝试。它只是遍历参数并检查它们是否以-
开头。如果是这样,并且下一个参数没有,则将这两个项添加到一个词典中,否则添加当前参数和True
。如果参数列表中的最后一项以try
开头,则需要-
。
args = "-t 500 -x -c 3 -d".split()
d = {}
for i, item in enumerate(args):
if item.startswith('-'):
try:
if args[i+1].startswith('-'):
d[item] = True
else:
d[item] = args[i+1]
except IndexError:
d[item] = True
print d # prints {'-t': '500', '-x': True, '-c': '3', '-d': True}
修改:受Gerrat's splitting on -
启发的替代解决方案如下:
args = "-t 500 -x -c 3 -d".split('-')
d = {}
for arg in args:
if arg:
try:
k, v = arg.split()
except ValueError:
k, v = arg.strip(), True
d[k] = v
但是,正如马蒂亚斯指出的那样,如果选项和值中包含-
,这可能无效。
答案 6 :(得分:0)
import re
myDictionnary = {}
strPattern1 = "-[0-9a-z ]*"
strPattern2 = "-([0-9a-z]+) *(.*)"
strToParse = "-t 500 -x -c 3 -d"
listKeyValues = re.findall(strPattern1, strToParse)
for kv in listKeyValues:
match = re.search(strPattern2, kv)
key = match.group(1)
value = match.group(2)
if len(value) > 0:
myDictionnary[key] = value
else:
myDictionnary[key] = True