簡體   English   中英

在python中特定子字符串之前找到第一個模式

[英]Find the first pattern before the specific substring in python

在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_* texture* ,我知道這個名字。

因此,例如,如果我有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 = ?

或者以其他任何方式,如果您認為自己知道更好的一種。

嘗試這個:

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'}

反復:

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

誰喜歡正則表達式可能會喜歡這種方法的可讀性和效率。

re.findall()返回輸入數據re.findall()則表達式的所有匹配項的匹配組序列(方括號中的regexp部分)。 因此,正則表達式查找“​​ newmtl”行中緊隨其后的“ map_Kd”行中所有出現的內容,並使用正則表達式組從這些行中提取值部分。 然后,通過字典理解將值反轉以創建所需的字典。

我喜歡此解決方案,因為它既緊湊又高效。 請注意,我在原始示例中僅添加了一個(多行)表達式(准確地說是一個導入)。 如果您可以閱讀正則表達式,那么它也很容易閱讀。

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]

此示例中的正則表達式適用於給定的數據。 如果您需要對源數據中的空格或其他類型的可變性更嚴格或更寬容,則可能需要進一步調整。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM