按空格拆分,保留花括号内的字符串

3
str = "cmd -opt1 { a b c  d e f g h } -opt2" 

我希望得到这样的输出:
[ 'cmd', '-opt1', '{ a b c  d e f g h }', '-opt2' ]  

2
那么你的代码在哪里,它到底有什么问题?这似乎是命令行输入,为什么你要手动解析它,而不是通过 sys.argv 获取它呢? - jonrsharpe
此字符串不是来自命令行输入。 - Deepak Yadav
1
那么它到底是从哪里来的?这很可能是一个XY问题,在你达到这一步之前就可以解决。 - jonrsharpe
我找到了这个链接 - 最接近我的问题 https://dev59.com/qF8d5IYBdhLWcg3wcx5V。但我想可能还有更简单的解决方案。 - Deepak Yadav
"我猜应该还有更简单的解决方案" - 为什么? - jonrsharpe
显示剩余2条评论
4个回答

5
在这种情况下,不要尝试分割,使用re.findall:
>>> import re
>>> re.findall(r'{[^}]*}|\S+', 'cmd -opt1 { a b c  d e f g h } -opt2')
['cmd', '-opt1', '{ a b c  d e f g h }', '-opt2']

如果你需要处理嵌套花括号,那么re模块就不够用了,你需要使用带有递归功能的“新”正则表达式模块regex

>>> import regex
>>> regex.findall(r'[^{}\s]+|{(?:[^{}]+|(?R))*+}', 'cmd -opt1 { a b {c d} e f} -opt2')
['cmd', '-opt1', '{ a b {c d} e f}', '-opt2']

(?R)指的是整个模式本身。

或者也可以使用以下更清晰的表述:

regex.findall(r'[^{}\s]+|{[^{}]*+(?:(?R)[^{}]*)*+}', 'cmd -opt1 { a b {c d} e f} -opt2')

我还想解析带有花括号的命令,例如 "cmd -opt1 { a b {c d} e f} -opt2"。因此输出应该是:['cmd', '-opt1', '{ a b {c d} e f}', '-opt2']。这种情况是否也有可能呢? - Deepak Yadav
@DeepakY:是的,这是可能的,但不能使用re模块,你需要使用“新”的regex模块:https://pypi.python.org/pypi/regex,它允许递归模式:`regex.findall(r'[^{}\s]+|{(?>[^{}]+|(?R))*}', 'cmd...` - Casimir et Hippolyte

3

1
请看 argparse模块,因为我假设您正在编写解析程序参数的代码。通常这些参数存储在sys.argv中,因此您甚至不需要担心分割命令行字符串。如果您坚持使用命令行,则可以使用str.split方法将参数字符串转换为参数列表。
import argparse

parser = argparse.ArgumentParser(description='whatever cmd does.')
parser.add_argument('--opt1', metavar='N', type=int, nargs='+',
                   help='integers')

options = parser.parse_args()

for n in options.opt1:
   # do something with n

我认为 parse_args 方法期望一个列表,就像从 sys.argv 中获取的那样;它能正确地处理一个字符串吗? - jonrsharpe
默认情况下,它使用 sys.argv。它不能处理字符串(将其视为字符列表)。 - xtofl
如果原帖的数据类型是字符串,这样怎样帮助他们呢?你至少应该在回答中清楚地包含这个警示。 - jonrsharpe
“您可以使用str.split方法将参数字符串转换为参数列表” - 这正是他们遇到困难的地方,因为他们的字符串包含一些希望按其进行分割的空格和一些不需要分割的空格... - jonrsharpe
感谢@jonrsharpe。我有一种指向与问题不直接相关的解决方案的本领。难道你不认为这是一个设计问题吗:解析将被另一个程序使用的字符串?不使用标准可用组件,就像这里一样,会导致大量不真正需要的代码。这就是我发布这个答案的原因。 - xtofl
“你不觉得这是一个设计问题吗?” - 我认为可能是,我已经试图向OP澄清为什么这是一个要求! - jonrsharpe

0

只需在{}上分割,然后通过正常空格分割各个部分:

str = "cmd -opt1 { a b c d e f g h } -opt2"
>>> a, b = str.split("{")
>>> c, d = b.split("}")
>>> a.split() + ["{{{0}}}".format(c)] + d.split()
['cmd', '-opt1', '{ a b c d e f g h }', '-opt2']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接