【问题标题】:PYTHON all possibilities of command with optional and mandatory parametersPYTHON 带有可选和强制参数的所有命令可能性
【发布时间】:2021-06-10 06:17:03
【问题描述】:

我正在努力列出 python 中带有可选和强制参数的命令的所有可能性。我需要它根据一些脚本的帮助输出在 bash 中生成一些自动完成脚本。

例如虚构的命令:

add disk -pool <name> { -diskid <diskid> | -diskid auto [-fx | -tdr] } [-fx] [-status { enable | disable } ]

其中:{} 必填,[] 可选,|或

上述命令的所有(24)种可能性的预期结果:

add disk -pool <name> -diskid <diskid>
add disk -pool <name> -diskid <diskid> -capacity_saving
add disk -pool <name> -diskid <diskid> -capacity_saving -status enable
add disk -pool <name> -diskid <diskid> -capacity_saving -status disable
add disk -pool <name> -diskid <diskid> -status enable
add disk -pool <name> -diskid <diskid> -status disable
add disk -pool <name> -diskid auto
add disk -pool <name> -diskid auto -capacity_saving
add disk -pool <name> -diskid auto -capacity_saving -status enable
add disk -pool <name> -diskid auto -capacity_saving -status disable
add disk -pool <name> -diskid auto -status enable
add disk -pool <name> -diskid auto -status disable
add disk -pool <name> -diskid auto -fx 
add disk -pool <name> -diskid auto -fx -capacity_saving
add disk -pool <name> -diskid auto -fx -capacity_saving -status enable
add disk -pool <name> -diskid auto -fx -capacity_saving -status disable
add disk -pool <name> -diskid auto -fx -status enable
add disk -pool <name> -diskid auto -fx -status disable
add disk -pool <name> -diskid auto -tdr 
add disk -pool <name> -diskid auto -tdr -capacity_saving
add disk -pool <name> -diskid auto -tdr -capacity_saving -status enable
add disk -pool <name> -diskid auto -tdr -capacity_saving -status disable
add disk -pool <name> -diskid auto -tdr -status enable
add disk -pool <name> -diskid auto -tdr -status disable

我试过import intertool + product(),但它只适用于不太复杂的命令,如{ -diskid &lt;diskid&gt; | -diskid auto },所以如果括号中没有更多的括号,如下面的命令输出:

# add disk -pool <name> { -diskid <diskid> | -diskid auto } [-fx]

command = [ ['add'], ['disk'], ['-pool <name>'], ['-diskid <diskid>', '-diskid auto'], ['', '-fx']]   
print(list(itertools.product(*command)))
print(len(list(itertools.product(*command))))

输出:

[('add', 'disk', '-pool <name>', '-diskid <diskid>', ''), 
('add', 'disk', '-pool <name>', '-diskid <diskid>', '-fx'), 
('add', 'disk', '-pool <name>', '-diskid auto', ''), 
('add', 'disk', '-pool <name>', '-diskid auto', '-fx')]
4

我怎样才能得到预期的结果? :c

【问题讨论】:

  • not :( 我只是想从一个字符串(命令字符串)中知道有多少种可能性(基于语法命令的规则,如 [ ... ],{ ... })

标签: python combinatorics


【解决方案1】:

以下解决方案采用更通用的方法。首先,parse_commands 将字符串命令转换为列表和字典的嵌套对象,然后command_combosparse_commands 生成的对象中生成所有可能的命令组合:

import re, collections itertools
s = 'add disk -pool <name> { -diskid <diskid> | -diskid auto [-fx | -tdr] } [-fx] [-status { enable | disable } ]'
symbols = {'|':None, '{':'}', '[':']'}
def parse_command(s, f = False, t = None):
   #take in a string command and parse it
   b = []
   while s:
      n = s.popleft()
      if f:
         if t is None and n in [*symbols, *symbols.values()]:
            s.appendleft(n)
            break
         if t is not None and n == symbols[t]:
            break
      if n not in [*symbols, *symbols.values()]:
         b.append(n)
      elif n == '|':
         b = [{'action':'or', 'blocks':(b, list(parse_command(s, f = True, t = None)))}]
      else:
         b.append({'action':{'{':'mandatory', '[':'optional'}[n], 'blocks':list(parse_command(s, f = True, t = n))})
   yield from b

def command_combos(d, c = []):
   #recursively traverse parsed command and produce combinations
   if not d:
      yield c
   else:
      if isinstance(d[0], str):
         yield from command_combos(d[1:], c+[d[0]])
      else:
         if d[0]['action'] == 'optional':
            yield from command_combos(d[1:], c)
         for b in (d[0]['blocks'] if d[0]['action'] == 'or' else [d[0]['blocks']]):
            for i in command_combos(b, []):
                yield from command_combos(d[1:], c+i)

把它们放在一起:

new_s = list(parse_command(collections.deque(re.findall('[\{\[\}\]\|]|\-*\<*\w+\>*', s))))
combos = list(command_combos(new_s))  

输出:

[['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-fx', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', '<diskid>', '-tdr', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-fx', '-fx', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr', '-status', 'disable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr', '-fx'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr', '-fx', '-status', 'enable'], ['add', 'disk', '-pool', '<name>', '-diskid', 'auto', '-tdr', '-fx', '-status', 'disable']]

【讨论】:

  • hmm 出了点问题,因为可能的总数是 36,应该是 24 - 问题仅适用于 -diskid &lt;diskid&gt;add disk { -diskid &lt;diskid&gt; | -diskid auto [-fx | -tdr] 0 ...}[-fx | -tdr] 不应添加到 -diskid &lt;diskid&gt; 仅适用于 @987654331 @
【解决方案2】:

您为虚构命令提供的语法与预期输出不匹配(例如 -capacity_saving)。

尽管如此:

import itertools


# OP syntax :
# add disk -pool <name> { -diskid <diskid> | -diskid auto [-fx | -tdr] } [-fx] [-status { enable | disable } ]
command = (
    # one mandatory diskid
    ("-diskid <diskid>", "-diskid auto", "-diskid auto -fx", "-diskid auto -tdr"),
    # one optional fx
    (None, "-fx"),
    # one optional status
    (None, "-status enable", "-status disable")
)

prefix = "add disk -pool <name> "

all_usages = tuple(itertools.product(*command))
print("\n".join(str(prefix + tuple(filter(lambda arg: arg is not None, usage))) for usage in all_usages))
print("total:", len(all_usages))

给我

('add', 'disk', '-pool', '<name>', '-diskid <diskid>')
('add', 'disk', '-pool', '<name>', '-diskid <diskid>', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid <diskid>', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid <diskid>', '-fx')
('add', 'disk', '-pool', '<name>', '-diskid <diskid>', '-fx', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid <diskid>', '-fx', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto')
('add', 'disk', '-pool', '<name>', '-diskid auto', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto', '-fx')
('add', 'disk', '-pool', '<name>', '-diskid auto', '-fx', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto', '-fx', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx', '-fx')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx', '-fx', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto -fx', '-fx', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr', '-status disable')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr', '-fx')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr', '-fx', '-status enable')
('add', 'disk', '-pool', '<name>', '-diskid auto -tdr', '-fx', '-status disable')
total: 24

【讨论】:

  • 非常感谢,你只是愚蠢的错误-capacity_saving 应该替换为第二个-fx
猜你喜欢
  • 2020-05-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-25
  • 2022-07-06
  • 2018-03-22
  • 2015-12-23
  • 2015-07-05
  • 2018-08-11
相关资源
最近更新 更多