Разбор и прерывание длинной строки в Python - PullRequest
2 голосов
/ 29 февраля 2012

Я искал, но не нашел что-то для своего дела. По сути, я пытаюсь разбить следующую строку:

(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, но у меня возникли некоторые проблемы.

Кроме того, он также может иметь следующие условия:

  • !
  • <</li>
  • >
  • =
  • ! =
  • ! <</li>
  • !>

На данный момент у меня есть это:

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)

1 Ответ

2 голосов
/ 29 февраля 2012

Вот решение с использованием регулярного выражения, отредактированное для включения префикса 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 символов, регулярное выражение, которое мы будем использовать для получения этих строк, не будет содержать префикс или закрывающие скобки, поэтому maxlen равно 64 - len(prefix).

Теперьчто мы знаем наибольшее количество символов, с которыми мы можем сопоставить, первая часть регулярного выражения (.{1,<maxlen>) будет соответствовать не более, чем столько символов.Часть в конце, (?:$|:), используется, чтобы убедиться, что мы разбиваем строку только на точки с запятой или в конце строки.Поскольку существует только одна группа захвата, 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().Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...