最佳方法将字符串按最后一个空格分割

3
我想知道将由空格分隔的字符串拆分为字符串中的最后一个空格的最佳方法,该空格不在[, {, ( or "内。例如,我可能有:
a = 'a b c d e f "something else here"'
b = 'another parse option {(["gets confusing"])}'

对于 a,它应该解析为['a','b','c','d','e','f'], ["something else here"]
而 b 应解析为 ['another','parse','option'],['([{"gets confusing"}])']

现在我有这个:

def getMin(aList):  
    min = sys.maxint
    for item in aList:  
        if item < min and item != -1:
            min = item
    return min  

myList = []
myList.append(b.find('['))
myList.append(b.find('{'))
myList.append(b.find('('))
myList.append(b.find('"'))
myMin = getMin(myList)
print b[:myMin], b[myMin:]

我相信有更好的方法来做这件事,也欢迎各种建议。


在引号或括号中是否可以有多个字符串,还是总是以单个字符串结尾? - Jonathan Villemaire-Krajden
最终结果永远只有一个。 - Chrispresso
有一个漂亮、干净、简单的解决方案,给我一点时间。 :) - zx81
3个回答

2

您可以使用正则表达式:

import re
def parse(text):
    m = re.search(r'(.*) ([[({"].*)', text)
    if not m:
        return None
    return m.group(1).split(), [m.group(2)]

第一部分(.*)捕获引号或括号中的所有内容,第二部分捕获任何以([{"字符开头的内容。

如果您需要更强大的功能,可以使用更复杂的正则表达式,但它将确保匹配开放标记,并使最后一个表达式可选。

def parse(text):
    m = re.search(r'(.*?)(?: ("[^"]*"|\([^)]*\)|\[[^]]*\]|\{[^}]*\}))?$', text)
    if not m:
        return None
    return m.group(1).split(), [m.group(2)]

这个正则表达式将捕获参数中有多个组的情况:re.findall(r'"[^"]*"|\([^)]*\)|\[[^]]*\]|\{[^}]*\}|[^ ]+', text) - Jonathan Villemaire-Krajden
不错,但它无法优雅地处理孤立的括号或引号。 - m.wasowski
@m.wasowski:我添加了一个更健壮的正则表达式,确保开放令牌是平衡的。 - Jonathan Villemaire-Krajden

2

匹配与拆分

有一个简单的解决方案。关键在于理解匹配和拆分是同一件事情的两个方面。当你说“匹配所有”时,这意味着“在我不想匹配的地方进行拆分”,反之亦然。我们将不再进行拆分,而是进行匹配,最终得到相同的结果。

精简版

让我们从最简单的正则表达式开始,这样您就不会被一些很长的东西吓到:

{[^{}]*}|\S+

这将匹配第二个字符串中的所有项,就像我们正在拆分一样(请参见演示)。

  • |替代符号的左侧匹配完整的{大括号}集合。
  • |替代符号的右侧匹配不是空格字符的任何字符。

就是这么简单!

完整的正则表达式

我们还需要匹配"完整的引号"(完整的括号)[完整的方括号]。没问题:我们只需将它们添加到替换符号中。为了清晰起见,我将它们放在一个非捕获组(?:中,以便\S+单独出现,但没有必要。

(?:{[^{}]*}|"[^"]*"|\([^()]*\)|\[[^][]*\])|\S+

请查看演示注意潜在的改进:
  • 我们可以用接受转义引号的正则表达式来替换带引号的字符串正则表达式。
  • 我们可以将大括号、方括号和圆括号表达式替换为递归表达式,以允许嵌套构造,但您必须使用Matthew Barnett的(令人敬畏的)regex模块而不是re
  • 该技术与一种简单而美妙的技巧相关,可以匹配(或替换)除...之外的模式
如果您有任何问题,请告诉我!

1

应该也适用于不同类型的括号,太棒了! - m.wasowski
在这种情况下,shelx并不是很有用,因为它只擅长拆分引号。我知道我可以使用它来按照我想要的方式进行拆分,但那需要操作shlex.spacesshlex.quotes等,并编写一个子解析器来获取中间数据。 - Chrispresso
@user2599709 如果这不满足您的需求,请在问题中添加使用情况,说明何时它无法正常工作。 - m.wasowski
@m.wasowski 你试过正则表达式吗?有什么原因不能采用这种方法吗? - A A
@m.wasowski 如果我使用 shlex 并基于空格进行分割,那就无法满足我在原始问题中提供的要求。Shlex 会在所有空格处进行分割,包括我不想要的字符之间的空格。 - Chrispresso

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