如何将表示 Bash 命令元素的列表元素组合到具有等号的新列表

how to combine the elements of a list representing the elements of a Bash command to a new list featuring the equals symbol

我有如下列表:

commandOptionsAndArguments = ['myBigTool', '--num-callers', '30', '--leak-check', 'full', '--tool', 'memcheck', '--suppressions', 'etc/valgrind-root.supp', '--suppressions', 'Gaudi.supp/Gaudi.supp', '--suppressions', 'oracleDB.supp', '--suppressions', 'valgrindRTT.supp', '--suppressions', 'root.supp/root.supp', '--mySpecialFlag', '$(which python)', '$(which athena.py)', 'athenaConf.pkl']

此列表由 Bash 命令的元素组成,这些元素具有选项,如果有的话,还有它们各自的参数。我想将其转换为以下列表:

commandOptions = ['myBigTool', '--num-callers=30', '--leak-check=full', '--tool=memcheck', '--suppressions=etc/valgrind-root.supp', '--suppressions=Gaudi.supp/Gaudi.supp', '--suppressions=oracleDB.supp', '--suppressions=valgrindRTT.supp', '--suppressions=root.supp/root.supp', '--mySpecialFlag', '$(which python)', '$(which athena.py)', 'athenaConf.pkl']

这个新列表包含选项,如果有的话,它们各自的参数使用等号组合成新元素。下一步是使用子进程执行此命令或将其转换为字符串以用于 os.system:

" ".join(commandOptions)
# 'myBigTool --num-callers=30 --leak-check=full --tool=memcheck --suppressions=etc/valgrind-root.supp --suppressions=Gaudi.supp/Gaudi.supp --suppressions=oracleDB.supp --suppressions=valgrindRTT.supp --suppressions=root.supp/root.supp --mySpecialFlag $(which python) $(which athena.py) athenaConf.pkl'

我的问题是:如何以稳健的方式将列表 commandOptionsAndArguments 更改为列表 commandOptions,同时适当地检测带参数和不带参数的选项?

(此外,如果有人对所提到的列表有更好的名称,请随时提出建议。我不确定应该使用哪些词来描述使用等号指定参数的方式命令选项而不是使用空格。)

您可以使用切片:

>>> [commandOptionsAndArguments[0]]+['='.join(commandOptionsAndArguments[1:][i:i+2]) for i in range(0,len(commandOptionsAndArguments)-1,2)]
['myBigTool', '--num-callers=30', '--leak-check=full', '--tool=memcheck', '--suppressions=etc/valgrind-root.supp', '--suppressions=Gaudi.supp/Gaudi.supp', '--suppressions=oracleDB.supp', '--suppressions=valgrindRTT.supp', '--suppressions=root.supp/root.supp', '--mySpecialFlag=$(which python)', '$(which athena.py)=athenaConf.pkl']
>>> 

您可以在此处使用 re 模块。

>>> commandOptionsAndArguments = ['myBigTool', '--num-callers', '30', '--leak-check', 'full', '--tool', 'memcheck', '--suppressions', 'etc/valgrind-root.supp', '--suppressions', 'Gaudi.supp/Gaudi.supp', '--suppressions', 'oracleDB.supp', '--suppressions', 'valgrindRTT.supp', '--suppressions', 'root.supp/root.supp', '--mySpecialFlag', '$(which python)', '$(which athena.py)', 'athenaConf.pkl']
>>> re.split(r'\s+(?![^()]*\))', re.sub(r'(--\S+)\s+(\w\S+)', r'=', ' '.join(commandOptionsAndArguments)))
['myBigTool', '--num-callers=30', '--leak-check=full', '--tool=memcheck', '--suppressions=etc/valgrind-root.supp', '--suppressions=Gaudi.supp/Gaudi.supp', '--suppressions=oracleDB.supp', '--suppressions=valgrindRTT.supp', '--suppressions=root.supp/root.supp', '--mySpecialFlag', '$(which python)', '$(which athena.py)', 'athenaConf.pkl']

解释:

  • ' '.join(commandOptionsAndArguments) 以 space 作为分隔符连接给定列表中的所有元素。

  • 这替换了以 -- 开头的单词和以单词开头的单词( 之间的 spaces字符 ) 和 = 符号。这样它就不会替换 --mySpecialFlag$(which python) 之间的 space。

    re.sub(r'(--\S+)\s+(\w\S+)', r'=', ' '.join(commandOptionsAndArguments))
    
  • 最后这个 r'\s+(?![^()]*\))' 匹配一个或多个 space,它们不在 () 括号内。根据匹配的 spaces 拆分结果字符串将为您提供所需的输出。