【问题标题】:Parsing and chopping a long string in Python在 Python 中解析和截断长字符串
【发布时间】:2012-02-28 21:57:41
【问题描述】:

我已经搜索过,但没有找到适合我的情况的内容。基本上,我正在尝试拆分以下行:

(CU!DIVD:WEXP:DIVD-:DIVD+:RWEXP:RDIVD:RECL:RLOSS:MISCDI:WEXP-:INT:RGAIN:DIVOP:RRGAIN:DIVOP-:RDIVOP:RRECL:RBRECL:INT -:RRLOSS:INT +:RINT:RDIVD-:RECL-:RWXPOR:WEXPOR:MISCRE:WEXP+:RWEXP-:RBWEXP:RECL+:RRECL-:RBDIVD)

您可以将其解读为 CU 不是 DIVD 或 WEXP 或 DIV- 等等。如果超过 65 个字符,我想做的是将此行拆分为更易于管理的内容,如下所示:

(CU!DIVD:WEXP:DIVD-:DIVD+:RWEXP:RDIVD:RECL:RLOSS:MISCDI:WEXP-)
(CU!INT:RGAIN:DIVOP:RRGAIN:DIVOP-:RDIVOP:RRECL:RBRECL:INT-)
(CU!RRLOSS:INT +:RINT:RDIVD-:RECL-:RWXPOR:WEXPOR:MISCRE:WEXP+)
(CU!RWEXP-:RBWEXP:RECL+:RRECL-:RBDIVD)

它们都少于 65 个字符。这可以存储在列表中,我可以处理其余的事情。我开始使用 RegEx 来解决这个问题,但我遇到了一些麻烦。

此外,它还可以有以下条件:

  • >
  • =
  • !=
  • !>

到目前为止,我有这个:

def FilterParser(iteratorIn, headerIn):
    listOfStrings = []
    for eachItem in iteratorIn:
        if len(str(eachItem.text)) > 65:
             exmlLogger.error('The length of filter' + eachItem.text + ' exceeds the limit and will be dropped')
             pass
        else:
            listOfStrings.append(rightSpaceFill(headerIn + EXUTIL.intToString(eachItem),80))
return ''.join(stringArray)

【问题讨论】:

    标签: python regex string parsing


    【解决方案1】:

    这是一个使用正则表达式的解决方案,经过编辑以在每个新行的开头包含 CU! 前缀(或任何其他前缀):

    import re
    s = '(CU!DIVD:WEXP:DIVD-:DIVD+:RWEXP:RDIVD:RECL:RLOSS:MISCDI:WEXP-:INT:RGAIN:DIVOP:RRGAIN:DIVOP-:RDIVOP:RRECL:RBRECL:INT -:RRLOSS:INT +:RINT:RDIVD-:RECL-:RWXPOR:WEXPOR:MISCRE:WEXP+:RWEXP-:RBWEXP:RECL+:RRECL-:RBDIVD)'
    
    prefix = '(' + re.search(r'\w+(!?[=<>]|!)', s).group(0)
    maxlen = 64 - len(prefix)  # max line length of 65, prefix and ')' will be added
    regex = re.compile(r'(.{1,%d})(?:$|:)' % maxlen)
    lines = [prefix + line + ')' for line in regex.findall(s[len(prefix):-1])]
    
    >>> print '\n'.join(lines)
    (CU!DIVD:WEXP:DIVD-:DIVD+:RWEXP:RDIVD:RECL:RLOSS:MISCDI:WEXP-)
    (CU!INT:RGAIN:DIVOP:RRGAIN:DIVOP-:RDIVOP:RRECL:RBRECL:INT -)
    (CU!RRLOSS:INT +:RINT:RDIVD-:RECL-:RWXPOR:WEXPOR:MISCRE:WEXP+)
    (CU!RWEXP-:RBWEXP:RECL+:RRECL-:RBDIVD)
    

    首先我们需要获取前缀,我们使用re.search().group(0) 执行此操作,它会返回整个匹配项。最后的每一行最多应包含 65 个字符,我们将用于获取这些行的正则表达式将不包含前缀或右括号,这就是为什么 maxlen64 - len(prefix)

    现在我们知道我们可以匹配的字符最多,正则表达式(.{1,&lt;maxlen&gt;) 的第一部分将最多匹配那么多字符。末尾部分(?:$|:) 用于确保我们只在分号或字符串末尾拆分字符串。由于只有一个捕获组 regex.findall() 将只返回该匹配项,而省略尾随的分号。这是示例字符串的样子:

    >>> pprint.pprint(regex.findall(s[len(prefix):-1]))
    ['DIVD:WEXP:DIVD-:DIVD+:RWEXP:RDIVD:RECL:RLOSS:MISCDI:WEXP-',
     'INT:RGAIN:DIVOP:RRGAIN:DIVOP-:RDIVOP:RRECL:RBRECL:INT -',
     'RRLOSS:INT +:RINT:RDIVD-:RECL-:RWXPOR:WEXPOR:MISCRE:WEXP+',
     'RWEXP-:RBWEXP:RECL+:RRECL-:RBDIVD']
    

    列表推导用于通过将前缀和尾随) 添加到每个结果来构造所有行的列表。 s 的切片完成后,前缀和尾随 )regex.findall() 之前从原始字符串中剥离。希望这会有所帮助!

    【讨论】:

    • 这是一个很好的开始!我将如何“优雅地”剥离 CU! (或就此而言,任何字母数字和随附的条件)并将其附加到每个新行?
    • @mastashake57 - 抱歉,我好像错过了你的问题,现在正在编辑。
    • 谢谢,F.J.,你在帮助我。顺便说一句,完全感谢故障。
    • @mastashake57 - 好的,看看我修改后的答案,它现在应该可以做你想做的了。
    • @mastashake57 - 将已编译正则表达式的第二部分从 (?:$|:) 更改为 (?:$|[:~])
    猜你喜欢
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 2014-11-03
    • 2017-10-30
    • 1970-01-01
    相关资源
    最近更新 更多