Разделите строку, содержащую несколько ключевых слов, в список, используя Python - PullRequest
1 голос
/ 18 января 2012

Я пытаюсь проанализировать файл конфигурации / etc / network / interfaces в Ubuntu, поэтому мне нужно разделить строку на список строк, где каждая строка начинается с одного из заданных ключевых слов.

Согласно инструкции:

Файл состоит из нуля или более разделов "iface", "mapping", "auto", "allow-" и "source".

Итак, если файл содержит:

auto lo eth0
allow-hotplug eth1

iface eth0-home inet static
    address 192.168.1.1
    netmask 255.255.255.0

Я хотел бы получить список:

['auto lo eth0', 'allow-hotplug eth1', 'iface eth0-home inet static \ n address ...']

Теперь у меня есть такая функция:

def get_sections(text):
    start_indexes = [s.start() for s in re.finditer('auto|iface|source|mapping|allow-', text)]
    start_indexes.reverse()
    end_idx = -1
    res = []
    for i in start_indexes:
        res.append(text[i: end_idx].strip())
        end_idx = i
        res.reverse()
    return res

Но это нехорошо ...

Ответы [ 2 ]

3 голосов
/ 18 января 2012

Вы можете сделать это в одном регулярном выражении:

>>> reobj = re.compile("(?:auto|allow-|iface)(?:(?!(?:auto|allow-|iface)).)*(?<!\s)", re.DOTALL)
>>> result = reobj.findall(subject)
>>> result
['auto lo eth0', 'allow-hotplug eth1', 'iface eth0-home inet static\n    address 192.168.1.1\n    netmask 255.255.255.0']

Объяснение:

(?:auto|allow-|iface)   # Match one of the search terms
(?:                     # Try to match...
 (?!                    #  (as long as we're not at the start of
  (?:auto|allow-|iface) #  the next search term):
 )                      #  
 .                      # any character.
)*                      # Do this any number of times.
(?<!\s)                 # Assert that the match doesn't end in whitespace

Конечно, вы также можете отобразить результаты в списоккортежи в соответствии с вашим комментарием:

>>> reobj = re.compile("(auto|allow-|iface)\s*((?:(?!(?:auto|allow-|iface)).)*)(?<!\s)", re.DOTALL)
>>> result = [tuple(match.groups()) for match in reobj.finditer(subject)]
>>> result
[('auto', 'lo eth0'), ('allow-', 'hotplug eth1'), ('iface', 'eth0-home inet static\n    address 192.168.1.1\n    netmask 255.255.255.0')]
2 голосов
/ 18 января 2012

Вы были очень близки к чистому решению, когда вычисляли стартовые показатели.С их помощью вы можете добавить одну строку для извлечения необходимых ломтиков:

indicies = [s.start() for s in re.finditer(
            'auto|iface|source|mapping|allow-', text)]
answer = map(text.__getslice__, indicies, indicies[1:] + [len(text)])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...