如何从字符串中便捷提取命令行标志并转为字典?
推荐几个可行的方案,完美匹配你的需求!
1. 用第三方模块 docopt(最省心的现成方案)
docopt 就是专门用来解析命令行风格字符串的工具,完全符合你要的规则:支持短横线-和长横线--的标志,自动把标志后的非标志内容作为值,没有参数的标志会对应None,而且不会随便触发SystemExit。
首先安装它:
pip install docopt
然后用你的例子来演示:
from docopt import docopt # 定义通用匹配模式,适配所有--xxx或-xxx的标志 pattern = """ Usage: script [options] Options: -h, --help Show help * Catch all dynamic options """ # 第一个测试字符串 str1 = "--test arg1 arg2 --test2" result1 = docopt(pattern, argv=str1.split()) # 整理成你要的字典格式(去掉标志前的横线) cleaned1 = {k.lstrip('-'): v if v != [] else None for k, v in result1.items() if k.startswith('-')} print(cleaned1) # 输出: {'test': 'arg1 arg2', 'test2': None} # 第二个测试字符串 str2 = "--test -test2 --test3 arg arg arg" result2 = docopt(pattern, argv=str2.split()) cleaned2 = {k.lstrip('-'): v if v != [] else None for k, v in result2.items() if k.startswith('-')} print(cleaned2) # 输出: {'test': None, 'test2': None, 'test3': 'arg arg arg'}
2. 改造 argparse 避免SystemExit
其实你之前用的argparse可以轻松改造,让它不触发退出。只需要自定义错误处理,或者捕获异常即可:
import argparse def parse_flags(s): tokens = s.split() parser = argparse.ArgumentParser() # 先遍历tokens,动态添加所有标志 i = 0 while i < len(tokens): token = tokens[i] if token.startswith(('-', '--')): flag_name = token.lstrip('-') # 判断下一个token是不是标志,决定是否添加参数接收 if i+1 < len(tokens) and not tokens[i+1].startswith(('-', '--')): parser.add_argument(token, nargs='*') else: parser.add_argument(token, action='store_true') i += 1 # 禁用默认的退出行为 parser.exit = lambda *args: None args, _ = parser.parse_known_args(tokens) # 转换为你要的字典格式 result = {} for k, v in vars(args).items(): if v is True: result[k] = None elif isinstance(v, list): result[k] = ' '.join(v) if v else None else: result[k] = v return result # 测试 print(parse_flags("--test arg1 arg2 --test2")) # {'test': 'arg1 arg2', 'test2': None} print(parse_flags("--test -test2 --test3 arg arg arg")) # {'test': None, 'test2': None, 'test3': 'arg arg arg'}
3. 自己写轻量解析器(无依赖)
如果不想用任何第三方模块,自己写一个解析器其实超简单,逻辑清晰完全可控:
def parse_flags(s): tokens = s.split() result = {} current_flag = None current_args = [] for token in tokens: if token.startswith(('-', '--')): # 处理上一个未完成的标志 if current_flag is not None: result[current_flag] = ' '.join(current_args) if current_args else None # 切换到新标志,去掉开头的横线 current_flag = token.lstrip('-') current_args = [] else: # 收集当前标志的参数 if current_flag is not None: current_args.append(token) # 处理最后一个标志 if current_flag is not None: result[current_flag] = ' '.join(current_args) if current_args else None return result # 测试 print(parse_flags("--test arg1 arg2 --test2")) # {'test': 'arg1 arg2', 'test2': None} print(parse_flags("--test -test2 --test3 arg arg arg")) # {'test': None, 'test2': None, 'test3': 'arg arg arg'}
这个轻量版本完全符合你的需求,没有任何依赖,还可以根据后续需求随时调整逻辑。
内容的提问来源于stack exchange,提问作者Kremla
相关产品推荐
相关产品推荐

