Python多行正则表达式+一次读取多个文件条目

0 投票
3 回答
2234 浏览
提问于 2025-04-16 15:52
//Last modified: Sat, Apr 16, 2011 09:55:04 AM
//Codeset: ISO-8859-1
fileInfo "version" "20x64";
createNode newnode -n "a_SET";
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" "blabla";
    setAttr -l on -k on ".test2" -type "string" "blablabla";
createNode newnode -n "b_SET";
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" "hmm";
    setAttr -l on -k on ".test2" -type "string" "ehmehm";

在Python中:

我需要读取一些新的节点名称,比如“a_SET”和“b_SET”,以及它们对应的属性值,比如{"a_SET": {"test1":"blabla", "test2":"blablabla"},b_SET也是类似的 - 可能会有不确定数量的集合,比如c_SET、d_SET等等。

我尝试过通过逐行循环来匹配这些内容:

for line in fileopened:
    setmatch = re.match( r'^(createNode set -n ")(.*)(_SET)(.*)' , line)
     if setmatch:
            sets.append(setmatch.group(2))

一旦我在这里找到匹配的内容,我就会继续循环下一行,以获取该集合的属性(test1、test2),直到我找到一个新的集合,比如c_SET,或者到达文件的结束。

有什么好的方法可以一次性抓取所有这些信息,使用re.MULTILINE吗?

3 个回答

0

还有一个可能的选项:

createNode newnode -n "b_SET";
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" (
      "hmm blablabla" );
    setAttr -l on -k on ".test2" -type "string" "ehmehm";

所以你可以看到".test1"的值现在是用/n换行符分开的。你会如何用eyquem的方法来解决这个问题呢?

pit = re.compile('^ *setAttr.+?("[^"\n]+").+("[^"\n]+");(?:\n|\Z)',re.MULTILINE)
3

你可以使用正则表达式中的正向前瞻来分割这些组:

(yourGroupSeparator)(.*?)(?=yourGroupSeparator|\Z)

在你的例子中:

import re

lines = open("e:/temp/test.txt").read()
matches = re.findall(r'createNode newnode \-n (\"._SET\");(.*?)(?=createNode|\Z)', lines, re.MULTILINE + re.DOTALL);

for m in matches:
    print "%s:" % m[0], m[1]


"""
Result:
>>>
"a_SET":
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" "blabla";
    setAttr -l on -k on ".test2" -type "string" "blablabla";

"b_SET":
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" "hmm";
    setAttr -l on -k on ".test2" -type "string" "ehmehm";
"""

如果你想把结果放到一个字典里,可以使用:

result = {}
for k, v in matches:
    result[k] = v   # or maybe v.split() or v.split(";")

在使用findall之后

0

我得到了这个:

import re

filename = 'tr.txt'

with open(filename,'r') as f:
    ch = f.read()

pat = re.compile('createNode newnode -n ("\w+?_SET");(.*?)(?=createNode|\Z)',re.DOTALL)
pit = re.compile('^ *setAttr.+?("[^"\n]+").+("[^"\n]+");(?:\n|\Z)',re.MULTILINE)

dic = dict( (mat.group(1),dict(pit.findall(mat.group(2)))) for mat in pat.finditer(ch)) 
print dic

结果

{'"b_SET"': {'".test2"': '"ehmehm"', '".test1"': '"hmm"'}, '"a_SET"': {'".test2"': '"blablabla"', '".test1"': '"blabla"'}}

.

问题:

如果字符串中必须包含字符 '"',那它是怎么表示的呢?

.

编辑

我在寻找解决方案时遇到了一些困难,因为我没有选择合适的工具。

这里有一个新的模式,它可以捕捉到第一个字符串 "..." 和最后一个字符串 "...",这些字符串出现在 " setAttr" 之后,并且在下一个 " setAttr" 之前。所以可能会有多个 "...",不仅仅是三个。你没有问这个条件,但我觉得可能会需要。

我还成功地让字符串中可以包含换行符,以便捕捉到 "....\n......",而不仅仅是它们周围的内容。为此,我不得不为自己发明一些新东西:(?:\n(?! *setAttr)|[^"\n]),这意味着:所有字符都可以接受,除了 '"' 和常见的 newlines \n,同时也只接受那些不跟在以 ' *setAttr' 开头的行后的换行符。

对于 (?:\n(?! *setAttr)|.),它的意思是:换行符后面不跟以 ' *setAttr' 开头的行,以及所有其他非换行字符。

因此,任何其他特殊序列,比如制表符或其他字符,都会自动被接受到匹配中。

ch = '''//Last modified: Sat, Apr 16, 2011 09:55:04 AM
//Codeset: ISO-8859-1
fileInfo "version" "20x64";
createNode newnode -n "a_SET";
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" "blabla";
    setAttr -l on -k on ".test2" -type "string" "blablabla";
createNode newnode -n "b_SET";
    addAttr -ci true -k true -sn "connections" -ln "connections" -dt "string";
    setAttr -l on -k off ".tx";
    setAttr -l on -k off ".ty";
    setAttr -l on -k off ".sz";
    setAttr -l on -k on ".test1" -type "string" (
      "hmm bl
      abla\tbla" );
    setAttr -l on -k on ".tes\nt\t2" -type "string" "ehm\tehm";
    setAttr -l on -k on ".test3" -type "string" "too
    much" "pff" """ "feretini" "gol\nolo";
    '''

import re

pat = re.compile('createNode newnode -n ("\w+?_SET");(.*?)(?=createNode|\Z)',re.DOTALL)
pot = re.compile('^ *setAttr.+?'
                 '"((?:\n(?! *setAttr)|[^"\n])+)"'
                 '(?:\n(?! *setAttr)|.)+'
                 '"((?:\n(?! *setAttr)|[^"\n])+)"'
                 '.*;(?:\n|\Z)',re.MULTILINE)

dic = dict( (mat.group(1),dict(pot.findall(mat.group(2)))) for mat in pat.finditer(ch)) 
for x in dic:
    print x,'\n',dic[x],'\n'

结果

"b_SET" 
{'.test3': 'gol\nolo', '.test1': 'hmm bl\n      abla\tbla', '.tes\nt\t2': 'ehm\tehm'} 

"a_SET" 
{'.test1': 'blabla', '.test2': 'blablabla'}

撰写回答