9

コマンドラインオプションを含む文字列を取得する最もPythonicな方法を見つけようとしています:

"-t 500 -x -c 3 -d"

そしてそれを辞書にします

{"-t":"500", "-x":True, "-c":"3", "-d": True}

UPDATE : 文字列には、 --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

しかし、それを行うと、PythonではなくCでプログラミングしているようです...

4

7 に答える 7

8

引用符内のスペースを正しく処理するには、次を使用できます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}
于 2012-08-17T21:58:15.407 に答える
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-]+)「-」または「--」で始まる任意の文字または単語 (単語でダッシュを使用できます) に一致します。
  • (.*?)は、疑問符を使用して、貪欲でないまたは最小限の方法で、任意の文字に 0 回以上一致します。
  • (?= -|$)前向きな先読みです。探しているものの後に「-」または文字列の末尾が続くことを確認しますが、一致には含まれません。

この正規表現での括弧の使用に注意してください。これらはグループを作成するために使用されるため、呼び出すfindallとタプルに分割されます。

于 2012-08-17T18:39:15.013 に答える
2

人間のための引数解析 - https://github.com/kennethreitz/args

于 2012-08-17T21:27:11.817 に答える
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」

これは:

  • {'-a': '-b'},
  • {'a-':真、'-b':真}

???

于 2012-08-17T17:29:47.877 に答える
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
于 2012-08-17T18:58:51.420 に答える
0

最初に出てくるより難しい問題、これは私の最初の試みです。引数をループして、引数が . で始まっているかどうかを確認するだけ-です。そうで、次の引数がそうでない場合、これら 2 つの項目が辞書に追加されます。それ以外の場合は、現在の引数と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の分割に-触発された代替ソリューションは次のとおりです。

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

ただし、Matthias が指摘しているように、オプションと値に-s が含まれている場合、これは機能しない可能性があります。

于 2012-08-17T17:44:06.297 に答える
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}

しかし、あなたが持っているものとかなり似ています..

于 2012-08-17T17:38:32.623 に答える