Python:如何分割合并某些行的行

时间:2017-01-30 10:32:06

标签: python split multiline

我想逐行处理字符串,但我想启用多行支持。这是示例文本:

First line
Second line
{{{
these three lines
I want to process
together
}}}
Last Line

我希望多行从{{{开始,然后在}}}结束 我曾经以下列方式逐行处理它:

lines = [l for l in text.splitlines()]
print lines

现在这段代码输出:

['First line', 'Second line', '{{{', 'these three lines', 'I want to process', 'together', '}}}', 'Last Line']

我想以某种方式让lines包含以下内容:

['First line', 'Second line', 'these three lines I want to process together', 'Last Line']

或者,更高级的例子

First Line
Second line
Third{{{line
fourth line
fifth}}}line
sixth line

在这种情况下,我希望行包含

['First Line', 'Second line', 'Third', 'line fourth line fifth', 'line', 'sixth line']

8 个答案:

答案 0 :(得分:3)

这是一个生成器,它将输入文件对象作为参数,并一次生成一行。它应该在同一行上接受尽可能多的{{{}}},但不会测试不平衡的构造:

def merge_lines(fd):
    concat = False
    for line in fd:
        while True:
            #print (line)
            if len(line.strip()) == 0: break
            if not concat:
                if ('{{{' in line):
                    deb, line = line.split('{{{', 1)
                    yield deb
                    concat = True
                    old = None
                else:
                    yield line.strip('\r\n')
                    line = ""
            if concat:
                if ('}}}' in line):
                    deb, line = line.split('}}}', 1)
                    concat = False
                    if old:
                        yield old.strip() + ' ' + deb
                    else: yield deb
                else:
                    if old:
                        old += ' ' + line.strip('\r\n')
                    else:
                        old = line.strip('\r\n')
                    line = ""

Python 3中的示例:

>>> t = """First line
a{{{b}}}c{{{d
e
f}}}g{{{h
i}}}
j
k
"""
>>> for line in merge_lines(io.StringIO(t)): print(line)

First line
a
b
c
d e f
g
h i
j
k

答案 1 :(得分:2)

使用正则表达式似乎是一个明智的解决方案 - 它为您提供了两个输入选项之间的灵活性

import re

only_line = '''First line
Second line
{{{
these three lines
I want to process
together
}}}
Last Line'''

mixed_line = '''First Line
Second line
Third{{{line
fourth line
fifth}}}line
sixth line'''

def curly_brackets(input_string):
    # regex - we want to match text before the backets, text in the brackets, and text after the brackets as three groups
    separate = list(re.findall('(.*)\{{3}(.*)\}{3}(.*)', input_string, re.DOTALL)[0])

    # 1-indexed item will be the value between brackets - replace carriage returns with spaces
    separate[1] = separate[1].replace('\n', ' ')

    # split according to new lines - there will be none in our bracketed section
    separate = [x.strip().split('\n') for x in separate]

    # flatten the lists down - each element of separate is currently a list
    return [x for sublist in separate for x in sublist]

print curly_brackets(only_line)
print curly_brackets(mixed_line)

返回:

['First line', 'Second line', 'these three lines I want to process together', 'Last Line']
['First Line', 'Second line', 'Third', 'line fourth line fifth', 'line', 'sixth line']

如果您有多组花括号,但是可以适应以迭代方式应用,那么这不会起作用。

答案 2 :(得分:0)

def split(text):    
    lines = []
    while '{{{' in text:
        head, sep, tail = text.partition('{{{')
        lines.extend(head.splitlines())
        head, sep, tail = tail.partition('}}}')
        lines.append(head.replace('\n', ' ').strip())
        text = tail

    lines.extend(text.splitlines())
    return lines

答案 3 :(得分:0)

这是我的解决方案。这很长很简单。我希望也许有一种方法可以在几行内完成它但是当}}}{{{在同一行时它不会处理案例

def _split_with_merging(text):
    lines = [l for l in text.splitlines() if l != ""]
    nlines = []
    multiline = False
    for l in lines:
        if multiline:
            if "}}}" in l:
                lparts = l.split("}}}")
                nlines[len(nlines) - 1] += lparts[0]
                if lparts[1] != "":
                    nlines.append(lparts[1])
                multiline = False
            else:
                nlines[len(nlines) - 1] += l
        else:
            if "{{{" in l:
                lparts = l.split("{{{")
                nlines.append(lparts[0])
                if lparts[1] != "":
                    nlines.append(lparts[1])
                multiline = True
            else:
                nlines.append(l)
    return nlines

答案 4 :(得分:0)

您可以使用正则表达式,假设您对 Console.Write(SpinnerAnimationFrames[currentAnimationFrame]); currentAnimationFrame++; if(currentAnimationFrame == SpinnerAnimationFrames.Length) { currentAnimationFrame = 0; } Console.SetCursorPosition(originalX, originalY); return currentAnimationFrame!=0?true:false; }

之间的行感兴趣
{{{ }}}}

OR

text = """First line
Second line
THIS{{{
these three lines
I want to process
together
}}}
Last Line"""

import re
match_obj = re.search('{{{(.*)}}}', text, re.DOTALL)
print match_obj.group(1)

OR

r = re.compile('{{{(.*)}}}', flags=re.DOTALL)
print re.split(r, text)
# replace \n
split_list = re.split(r, text)
split_list = [l.replace('\n', '') for l in split_list]
print split_list

如果在给定文本中多次出现match_list = re.findall('{{{(.*)}}}', text, re.DOTALL) match_list = [l.replace('\n', '') for l in match_list] print match_list ,请通过添加“?”来使用非贪婪匹配例如{{{ }}}

答案 5 :(得分:0)

我认为这可以作为您想要实现的目标的快速而简单的解决方案:

 @ElementList(entry= "PaymentTotals", inline = true, required = false)
 protected List<PaymentTotalsType> paymentTotals;

可能不是最干净的代码,我认为我们应该用text = """First line Second line {{{ these three lines I want to process together }}} Last Line""" all_lines = [l for l in text.splitlines()] final_list = [] nested = False for line in all_lines: if line == "{{{": nested = True multiline = "" continue elif line == "}}}": nested = False final_list.append(multiline) continue if nested == True: multiline = multiline + " " + line else: final_list.append(line) print(final_list) 替换multiline = multiline + " " + line,但我希望你能得到这个想法。

答案 6 :(得分:0)

在带有{{{标记的循环中跟踪开始}}}并关闭in_multi 直截了当:

def split_multi(s):
    lines = []
    in_multi = False
    for line in s.splitlines():
        if in_multi:
            if '}}}' in line:
                in_multi = False
                split = line.split('}}}')
                if split[0]:
                    tmp.append(split[0])
                lines.append(' '.join(tmp))
                if split[-1]:
                    lines.append(split[-1])
            else:
                tmp.append(line)
        else:
            if '{{{' in line:
                split = line.split('{{{')
                in_multi = True
                if split[0]:
                    lines.append(split[0])
                    if split[-1]:
                        tmp = [split[-1]]
                else:
                    tmp = []
            else:
                lines.append(line)

    return lines 


s1 = """First line
Second line
{{{
these three lines
I want to process
together
}}}
Last Line"""

s2 = """First Line
Second line
Third{{{line
fourth line
fifth}}}line
sixth line"""

print(split_multi(s1))
print(split_multi(s2))
#['First Line', 'Second line', 'Third', 'line fourth line fifth', 'line', 'sixth line']

输出:

['First line', 'Second line', 'these three lines I want to process together', 'Last Line']
['First Line', 'Second line', 'Third', 'line fourth line fifth', 'line', 'sixth line']

答案 7 :(得分:0)

我的2美分(使用joint):

// assuming that program is your compiled shader program and
// gl is your WebGL context.
const cos = Math.cos;
const sin = Math.sin;
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'camMatrix'), [
    cos(rY) * cos(rZ), cos(rZ) * sin(rX) * sin(rY) - cos(rX) * sin(rZ), sin(rX) * sin(rZ) + cos(rX) * cos(rZ) * sin(rY), 0,
    cos(rY) * sin(rZ), cos(rX) * cos(rZ) + sin(rX) * sin(rY) * sin(rZ), cos(rX) * sin(rY) * sin(rZ) - cos(rZ) * sin(rX), 0,
    -sin(rY), cos(rY) * sin(rX), cos(rX) * cos(rY), 0,
    0, 0, 0, 1
]);

返回:

ex1 = """First line
Second line
{{{
these three lines
I want to process
together
}}}
Last Line"""

ex2 = """First Line
Second line
Third{{{line
fourth line
fifth}}}line
sixth line"""

def parse_lines(txt, start_sep='{{{', end_sep='}}}'):
    depth = 0 # 1+ if we are inside a {{{ group
              # can be used to test unbalanced constructs
    lines = []
    current_line = ''
    n = len(txt)
    i = 0
    while i < n:
        c = txt[i]
        not_handled = True
        need_to_add = False
        if c == '\n': # end of line
            if depth == 0 : # save line and empty buffer
                need_to_add = True
            elif current_line != '': # add a space instead of the line break
                current_line = ''.join((current_line,' '))
            not_handled = False
            i += 1
        elif c == start_sep[0] and\
             txt[i:i+len(start_sep)] == start_sep:
             # ^ takes small advantage of lazy evaluation
             # (see questions/13960657)
                depth += 1
                need_to_add = True
                not_handled = False
                i += len(start_sep)
        elif c == end_sep[0] and\
             txt[i:i+len(end_sep)] == end_sep:
                depth -= 1
                need_to_add = True
                not_handled = False
                i += len(end_sep)
        if not_handled:
            current_line = ''.join((current_line,c))
            i += 1
        elif need_to_add and current_line != '':
            lines.append(current_line)
            current_line = ''
    if current_line != '': # add last line
        lines.append(current_line)
    return lines

请注意第一个示例中以>>> parse_lines(ex1) ['First line', 'Second line', 'these three lines I want to process together ', 'Last Line'] >>> parse_lines(ex2) ['First Line', 'Second line', 'Third', 'line fourth line fifth', 'line', 'sixth line'] 结尾的多线上的额外' '