【问题标题】:Find the first pattern before the specific substring in python在python中查找特定子字符串之前的第一个模式
【发布时间】:2019-12-16 06:11:35
【问题描述】:

在 Python 3.6.5 中,假设我有一个字符串,从文件中读取,如下所示:

# comments

newmtl material_0_2_8
Kd 1 1 1
Ka 0 0 0
Ks 0.4 0.4 0.4
Ke 0 0 0
Ns 10
illum 2
map_Kd ../images/texture0.png

newmtl material_1_24
Kd 1 1 1
Ka 0 0 0
Ks 0.4 0.4 0.4
Ke 0 0 0
Ns 10
illum 2

newmtl material_20_1_8
Kd 1 1 1
Ka 0 0 0
Ks 0.4 0.4 0.4
Ke 0 0 0
Ns 10
illum 2
d 1.0
map_Kd ../images/texture0.jpg

... and so on ...

我在循环每个纹理,需要获取对应的材质代码。

我想检索与某个texture*对应的子字符串material_*,我知道它的名字。

例如,如果我有texture0.jpg,我想返回material_20_1_8;如果我有texture0.png,那么我想要material_0_2_8

我该怎么做?

f=open('path/to/file', "r")
if f.mode == 'r':
    contents =f.read() # contains the string shown above
for texture in textures: # textures is the list of the texture names
    material_code = ?

或任何其他方式,如果您认为自己知道更好的方式。

【问题讨论】:

  • 只返回第一行,以防最后一行对应每个块的某个文件
  • 我认为最好做一个预处理阶段,在这个阶段你解析每个段落并将结果保存为,比如说,一个字典。从那里检索数据将是微不足道的material_code = materials[texture]
  • @AlexandreB。是的,已编辑。
  • @BlueRineS 如何划分块?
  • @Tomerikoo 我想避免更改原始文件或创建新文件

标签: python python-3.x string substring


【解决方案1】:

迭代:

import re

textures = ('texture0.jpg', 'texture0.png')
with open('input.txt') as f:
    pat = re.compile(r'\bmaterial_\S+')
    for line in f:
        line = line.strip()
        m = pat.search(line)
        if m:
            material = m.group()
        elif line.endswith(textures):
            print(line.split('/')[-1], material)

输出:

texture0.png material_0_2_8
texture0.jpg material_20_1_8

【讨论】:

    【解决方案2】:

    试试这个:

    mapping = {}
    with open('input.txt', 'r') as fin:
        for line in fin:
            if line.startswith('newmtl'):
                material = line[len('newmtl '):-1]
            elif line.startswith('map_Kd'):
                file = line.split('/')[-1][:-1]
                mapping[file] = material
    

    然后映射是dict 与您想要的关系:

    {'texture0.jpg': 'material_20_1_8', 'texture0.png': 'material_0_2_8'}
    

    【讨论】:

    • 好的,它可以工作,但文件实际上也有返回 '\n',我认为问题不包括,所以打印mapping 会给我{'texture0.png\n': 'material_0_2_8\n', 'texture0.jpg\n': 'material_20_1_8\n'},仍然很好回答
    【解决方案3】:

    喜欢正则表达式的人可能会喜欢这种方法的可读性和效率。

    re.findall() 为输入数据中正则表达式的所有匹配项返回一个匹配组序列(括号中的正则表达式部分)。因此,正则表达式找到所有出现的“newmtl”行以及最近的“map_Kd”行,并使用正则表达式组从这些行中提取值部分。然后通过dictionary comprehension 反转这些值以创建所需的字典。

    我喜欢这个解决方案,因为它紧凑且高效。请注意,我在原始示例中只添加了一个(嗯,多行)表达式(准确地说是一个导入)。如果你能看懂正则表达式,那它的可读性也很好。

    import re
    
    f = open('path/to/file', "r")
    if f.mode == 'r':
        contents = f.read()  # contains the string shown above
    
    materials = {
        filename: material for material, filename in 
        re.findall(r'^newmtl (material_\S+)$.*?^map_Kd \.\./images/(.+?)$', 
                   contents, re.MULTILINE | re.DOTALL)
    }
    
    for texture in textures: # textures is the list of the texture names
        material_code = materials[texture]
    
    

    此示例中的正则表达式适用于给定数据。如果您需要对源数据中的空白或其他类型的可变性更加严格或更宽松,则可能需要进一步调整。

    【讨论】:

      猜你喜欢
      • 2020-12-09
      • 1970-01-01
      • 2015-08-31
      • 2016-01-18
      • 2018-11-21
      • 2018-11-21
      • 2020-02-14
      • 1970-01-01
      • 2021-08-01
      相关资源
      最近更新 更多