Python正则表达式:从文本文件中提取关键字后的元组列表

Python正则表达式:从文本文件中提取关键字后的元组列表,python,regex,python-2.7,openfoam,freecad,Python,Regex,Python 2.7,Openfoam,Freecad,我想实现一个简化的版本,我建议从OpenFOAMblockMeshDict文件中导入一些顶点,然后 我感兴趣的文件部分是一个元组列表(xi yi zi)s浮点数,位于顶点关键字后的括号之间。该文件如下所示: vertices ( (1 2 3) (3 4 5) ... ) 我可以通过以下方式从与python脚本相同的文件夹中读取文件: import os os.chdir(os.path.dirname(__file__)) with open("blockMeshDi

我想实现一个简化的版本,我建议从OpenFOAM
blockMeshDict
文件中导入一些顶点,然后

我感兴趣的文件部分是一个元组列表
(xi yi zi)
s浮点数,位于
顶点
关键字后的括号之间。该文件如下所示:

vertices
(
    (1 2 3)
    (3 4 5)
    ...
)
我可以通过以下方式从与python脚本相同的文件夹中读取文件:

import os
os.chdir(os.path.dirname(__file__))
with open("blockMeshDict", "r") as f:
    s=f.read()
但是当我尝试提取
顶点后括号中的内容时,使用:

import re
r1=re.search(r'vertices\n\((.*?)\)', s)
print r1.group(1)
我得到一个错误:

键入“异常”。索引器错误:没有此类组


我不知道怎么解决它。最后我想要的是一个元组列表,如
[(x1,y1,z1),(x2,y2,z2)]
如果您能帮助我了解如何在Python2.7中实现这一点,我将不胜感激。

这将是找到外部结构的主要正则表达式:
\bvertices\s*(\s*(?:([^)]+\)\s*+)\

在此之前,我们将删除所有评论

然后是一个额外的正则表达式来提取顶点结构中的所有内容:
\([^]+\)

见演示

守则:

import re

test_str = """
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  5                                     |
|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

convertToMeters 0.001;

vertices
(
    (-20.6 0 -0.5)
    (-20.6 25.4 -0.5)  /* Some comment */
    (0 -25.4 -0.5)
    (0 0 -0.5)
    (0 25.4 -0.5)
    (206 -25.4 -0.5)
    (206 0 -0.5)
    (206 25.4 -0.5)
    (290 -16.6 -0.5)
    (290 0 -0.5)
    (290 16.6 -0.5)

    (-20.6 0 0.5)
    (-20.6 25.4 0.5)
    (0 -25.4 0.5)
    (0 0 0.5)
    (0 25.4 0.5)
    (206 -25.4 0.5)
    (206 0 0.5)
    (206 25.4 0.5)
    (290 -16.6 0.5)
    (290 0 0.5)
    (290 16.6 0.5)
  /*(1 2 3 4)*/ // Commented tuple
  //(1 2 3 4)
);

/* vertices commented
vertices
(
    (-20.6 0 -0.5)
    (-20.6 25.4 -0.5)
    (0 -25.4 -0.5)
    (0 0 -0.5)
    (0 25.4 -0.5)
    (206 -25.4 -0.5)
    (206 0 -0.5)
    (206 25.4 -0.5)
    (290 -16.6 -0.5)
    (290 0 -0.5)
    (290 16.6 -0.5)
)
*/

negY
(
    (2 4 1)
    (1 3 0.3)
);

posY
(
    (1 4 2)
    (2 3 4)
    (2 4 0.25)
);

posYR
(
    (2 1 1)
    (1 1 0.25)
);


blocks
(
    hex (0 3 4 1 11 14 15 12)
    (18 30 1)
    simpleGrading (0.5 $posY 1)

    hex (2 5 6 3 13 16 17 14)
    (180 27 1)
    edgeGrading (4 4 4 4 $negY 1 1 $negY 1 1 1 1)

    hex (3 6 7 4 14 17 18 15)
    (180 30 1)
    edgeGrading (4 4 4 4 $posY $posYR $posYR $posY 1 1 1 1)

    hex (5 8 9 6 16 19 20 17)
    (25 27 1)
    simpleGrading (2.5 1 1)

    hex (6 9 10 7 17 20 21 18)
    (25 30 1)
    simpleGrading (2.5 $posYR 1)
);

edges
(
);

boundary
(
    inlet
    {
        type patch;
        faces
        (
            (0 1 12 11)
        );
    }
    outlet
    {
        type patch;
        faces
        (
            (8 9 20 19)
            (9 10 21 20)
        );
    }
    upperWall
    {
        type wall;
        faces
        (
            (1 4 15 12)
            (4 7 18 15)
            (7 10 21 18)
        );
    }
    lowerWall
    {
        type wall;
        faces
        (
            (0 3 14 11)
            (3 2 13 14)
            (2 5 16 13)
            (5 8 19 16)
        );
    }
    frontAndBack
    {
        type empty;
        faces
        (
            (0 3 4 1)
            (2 5 6 3)
            (3 6 7 4)
            (5 8 9 6)
            (6 9 10 7)
            (11 14 15 12)
            (13 16 17 14)
            (14 17 18 15)
            (16 19 20 17)
            (17 20 21 18)
        );
    }
);
// ************************************************************************* //
"""

# Clean comments:
test_str = re.sub(r"//.*", '', test_str)
test_str = re.sub(r"/\*.*?\*/", '', test_str, 0, re.DOTALL)

# Match main group
matches = re.findall(r"\bvertices\s*\((\s*(?:\([^)]+\)\s*)+)\)", test_str, re.MULTILINE | re.DOTALL)

# Fetch tuples
matches2 = re.findall(r"\([^)]+\)", matches[0], re.MULTILINE | re.DOTALL)
print matches2
解释:

\b        # word boundary
vertices  # literal 'vertices'
\s*       # 0 or more spaces (includes line feed/carriage return)
\(        # literal '('
  (       # First capturing group
    \s*   # Som spaces
    (?:   # Group
       \([^)]+\)   # literal '(' + any non-')' character 1 or more times + literal ')'
       \s*         # extra spaces
    )+    # repeated one or more times
  )
\)        # literal ')'
然后,您获取捕获的组并搜索
\([^)]+\)
。这将查找顶点的实例

vertices
(
    (1 2 3)
    (3 4 5)
    ...
)
在中添加一个

如果希望将所有结果存储为列表(如中所示),则可能需要使用

r1 = re.findall(r'(?:vertices\s+)?(\([\w\s]+\))', s, re.DOTALL)
print r1

>>> ['(1 2 3)', '(3 4 5)']

我的测试数据文件
blockMeshDict

vertices // comment 1
(
          (1 2 3) // comment 2
/* :) */  (3 4 5) /* multi line...
...comment */

          (65.71 72.8 2.0)
)
代码:

输出是元组列表(浮点):


添加一个
re.DOTALL
,如
r1=re.search(r'vertices\n\(.*?)”,s,re.DOTALL)
。如果您想将所有结果存储为一个列表,您可能需要使用
re.findall
。@Tushortz感谢它现在像
(1,2,3
)一样打印第一个元组。@Tushortz我尝试了
findall
,现在它给出了
[\n(1 2 3']
r1=re.findall(r'(?:顶点\s+)(\([\w\,]+\)),s,re.DOTALL)
第一个正则表达式似乎不起作用。请参见此处:。第二个正则表达式可以匹配
foobar((1,2,3)(3))
而不仅仅是
顶点((1,2,3)(3))
。请参阅:。不确定这是否是OP的问题,although@Julio这不是OP要求的格式。OP问题与元组相关,元组之间用
分隔,因此答案仍然是valid@Tushortz我的错误。文件中的格式没有
。编辑了这篇文章。抱歉。数字之间只有空格好吧,他说:“我感兴趣的是一个元组(xi-yizi)的浮动列表,在顶点关键字后面的括号中,无论如何,如果没有其他可能的关键字不同于“顶点”在文件上,则无需检查vertices关键字anywaysawesome。这很好。现在输出为字符串列表。如何将其转换为元组?
(1 2 3)
-->
(1,2,3)
我编辑了这篇文章,数字之间没有
s。只有空格。但是你的代码工作得非常好!@Foad我更改了答案以允许评论。我还用示例文件测试了它(加上额外的评论)。请注意,接受的答案将与示例文件不匹配。请参阅:这是因为它与其他部分的元组匹配,如
negY
posY
posYR
blocks
。如果您不需要匹配这些元组,则可以使用此解决方案。您好,您想继续吗?您尝试过我的上一个解决方案了吗编辑?有什么东西丢失了吗?哦,很高兴听到这个问题的代码会被添加到这样一个大的开源项目中。如果你需要什么,就告诉Maynk很多。当你在准备这个帖子的时候,我不得不编辑OP,因为有一个错误。在数字之间没有<代码>,<代码> s。你介意编辑你的帖子吗?将输入的数字作为
(1 2 3)
?接受您在我的答案中所做的更改(添加了少量内容)。现在将数字作为浮点数读取(但不读取指数符号),并进行编辑,以使多行/*注释*/生效。这将是我的最后一次编辑。包括负数(和固定的多行注释(再次)
vertices // comment 1
(
          (1 2 3) // comment 2
/* :) */  (3 4 5) /* multi line...
...comment */

          (65.71 72.8 2.0)
)
import re

with open("blockMeshDict", "r") as f:
    s=f.read()

# Remove comments like "//" until end of line
s = re.sub(r'//.*', '', s)

# Remove comments between /* and */
s = re.sub(r'/\*(.|\s)*?\*/', '', s, re.DOTALL)

r1 = re.search(r'vertices\s*\(\s*(.*)\s*\)', s, re.DOTALL)
vertices = [(float(v[0]),float(v[1]),float(v[2]))
        for v in re.findall(r'\(\s*([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)\s*\)', r1.group(1))]

print(vertices)
[(1.0, 2.0, 3.0), (3.0, 4.0, 5.0), (65.71, 72.8, 2.0)]