【问题标题】:Divide string containing some keywords into list using Python使用Python将包含一些关键字的字符串划分为列表
【发布时间】:2012-02-13 04:07:51
【问题描述】:

我正在尝试在 Ubuntu 中解析 /etc/network/interfaces 配置文件,因此我需要将字符串划分为字符串列表,其中每个字符串都以给定关键字之一开头。

根据手册:

该文件由零个或多个“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

但这并不好......

【问题讨论】:

  • 或者,您可以使用confparse 之类的东西,它显然支持网络接口文件。
  • 您可以通过直接从 start_indexes 中提取切片来大大简化此代码。

标签: python regex parsing list


【解决方案1】:

您可以在单个正则表达式中完成:

>>> 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')]

【讨论】:

  • 第一次看起来有点复杂,但比我的版本短而且好得多。但是很难获得(组,字符串)的列表,例如[('auto', 'auto lo eth0'), ('iface', iface eth0 inet static'), ...]??
  • 是的。这就是我想要的。谢谢你:)
【解决方案2】:

当您计算开始指数时,您已经非常接近于一个干净的解决方案。有了这些,您可以添加一行来提取所需的切片:

indicies = [s.start() for s in re.finditer(
            'auto|iface|source|mapping|allow-', text)]
answer = map(text.__getslice__, indicies, indicies[1:] + [len(text)])

【讨论】:

  • 这也不错,但对我来说几乎不需要修复:map(text.__getslice__, indicies, indicies[1:] + [len(text)])
  • @marcinpz 好的,已根据您的要求进行了编辑。我认为这比创建一个巨大的、毛茸茸的正则表达式要干净得多。
猜你喜欢
  • 2020-03-03
  • 2020-10-03
  • 2021-12-19
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多