在Python中拆分C字符串

在Python中拆分C字符串,python,string,split,Python,String,Split,我想拆分一个类似于 'abc "defg hijk \\"l; mn\\" opqrs"; tuv' 进入 i、 我不想在(嵌套的)引号中使用分号。最简单的方法是什么,标记化?快一点也不痛,但短一点更好 编辑:我又忘了一个细节,这让事情变得更加棘手。我需要截断字符串的分号的位置,如果没有分号,则需要-1。(我正在对以前是递归的遗留代码进行更改,但是当字符串变得很长时堆栈溢出。)如果没有合适的解析器,不可能有简单的方法来解决这个问题。不过,您可能不需要使用手工构建的解析器进行标记化 以下内容应该

我想拆分一个类似于

'abc "defg hijk \\"l; mn\\" opqrs"; tuv'
进入

i、 我不想在(嵌套的)引号中使用分号。最简单的方法是什么,标记化?快一点也不痛,但短一点更好


编辑:我又忘了一个细节,这让事情变得更加棘手。我需要截断字符串的分号的位置,如果没有分号,则需要-1。(我正在对以前是递归的遗留代码进行更改,但是当字符串变得很长时堆栈溢出。)

如果没有合适的解析器,不可能有简单的方法来解决这个问题。不过,您可能不需要使用手工构建的解析器进行标记化

以下内容应该是一个很好的指南:

def parse(s):
    cur_s = []
    strings = []

    def flush_string():
        strings.push(''.join(cur_s))
        cur_s = []

    def handle_special_cases():
        # TODO: Fill this in

    for c in s:
        if c == ';':
            break
        elif c in ['\\' '"']:
            handle_special_cases()
        elif c == ' ':
            flush_string()
        else:
            cur_s.push(c)

    flush_string()
    return strings

这是一个有状态搜索,因此简单的无状态操作不可用。下面是一个简单的逐字符有状态计算器,它可以满足您的“简短”要求,而无需求助于完全标记化/解析:

#!/usr/bin/env python

inp="""abc "defg hijk \\"l; mn\\" opqrs"; tuv'`"""

def words_to_semi(inpstr):
    ret = ['']
    st8 = 1  # state: 1=reg, 2=in quotes, 3=escaped quote, 4=escaped reg, 0=end
    ops = { 1 : {' ': lambda c: (None,1),
                 '"': lambda c: (c,2),
                 ';': lambda c: ('',0),
                 '\\': lambda c: (c,4),
                 },
            2 : {'\\': lambda c: (c,3),
                 '"':  lambda c: (c,1),
                 },
            3 : {None: lambda c: (c,2)},
            4 : {None: lambda c: (c,1)},
            }
    pos = 0

    for C in inpstr:
        oc,st8 = ops[st8].get(C, ops[st8].get(None, lambda c:(c,st8)))(C)
        if not st8: break
        if oc is None:
            ret.append('')
        else:
            ret[-1] += oc
        pos = pos + 1
    return ret, pos

print str(words_to_semi(inp))

只需修改ops指令(并添加新状态)即可处理其他情况;其他一切都是通用代码。

这是我使用的暴力方法。Brrr

def f(s):
    instr = False
    inescape = False
    a = ''
    rs = []
    cut_index = -1
    for idx,ch in enumerate(s):
        if instr:
            a += ch
            if inescape:
                inescape = False
            elif ch == '\\':
                inescape = True
            elif ch == '"':
                if a:
                    rs += [a]
                    a = ''
                instr = False
        elif ch == '"':
            if a:
                rs += [a]
            a = ch
            instr = True
        elif ch == ';':
            if a:
                rs += [a]
            cut_index = idx
            break
        elif ch == ' ' or ch == '\t' or ch == '\n':
            if a:
                rs += [a]
                a = ''
        else:
            a += ch
    return rs, cut_index

f('abc "defg hijk \\"l; mn\\" opqrs"; tuv')

我看不出列表中第一个字符串和第二个字符串之间有什么区别。解释这个字符串是什么以及为什么它被拆分到你想要的位置可能有助于找到一个解决方案。第二个语句是两个字符串的列表,在引号外的分号后面的所有内容都被截断。@chown:几乎,它会在未命名的分号之后,在空格上拆分所有内容。是的,我刚才就是这么做的。又丑又慢,我本希望能有一个像蟒蛇一样的东西送给我如果您想要更“优雅”的东西,可以查看Python附带的内置解析器。您可以向他们提供语法,他们将为您生成解析器。缺点是,它们可能需要比上述解决方案更多的代码。看起来整洁,适用于简单的情况,但速度慢,没有捕获所有IRL,并且比暴力更慢。所以我不会花时间去修理,不过还是要谢谢你!
def f(s):
    instr = False
    inescape = False
    a = ''
    rs = []
    cut_index = -1
    for idx,ch in enumerate(s):
        if instr:
            a += ch
            if inescape:
                inescape = False
            elif ch == '\\':
                inescape = True
            elif ch == '"':
                if a:
                    rs += [a]
                    a = ''
                instr = False
        elif ch == '"':
            if a:
                rs += [a]
            a = ch
            instr = True
        elif ch == ';':
            if a:
                rs += [a]
            cut_index = idx
            break
        elif ch == ' ' or ch == '\t' or ch == '\n':
            if a:
                rs += [a]
                a = ''
        else:
            a += ch
    return rs, cut_index

f('abc "defg hijk \\"l; mn\\" opqrs"; tuv')