regex 正则表达式不返回行末尾的搜索字符串,并且不忽略带有$的行

wgxvkvu9  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(117)

从一个文本文件中,我想提取的一切,开始与特定的“关键字”,包括关键字,直到一个“end_word”,但不是end_word本身。也必须返回新行字符。每个提取的字符串都存储在字典中。我有下面的Python代码,除了:

我在输出中没有得到起始关键字,并且所有以$开头的行也被提取出来...

import re
keywords = [ "GRID" , "CHEXA" , "FORCE" , "FORCE*" , "MOMENT" , "MOMENT*"  ]
end_words = [ "GRID" , "CHEXA" , "FORCE" ,  "FORCE*" , "MOMENT" , "MOMENT*" , "\$" ]

# Create a regular expression pattern
end_words_pattern = "|".join(f"(?=.*{re.escape(word)})" for word in end_words)
    
# Read the file
CardsFound = {}
with open("D:/home/bdf_in_test_full.dat", "r") as file:
    file_data = file.read()
    for keyword in keywords:
        pattern = fr"^{re.escape(keyword)}((?:.*\n)+?(?={end_words_pattern}\n))"   
        matches = re.findall(pattern, file_data, re.MULTILINE | re.DOTALL)
        CardsFound[keyword] = matches

for keyword in keywords:
    print(CardsFound[keyword])
    print("\n\n")

我的输入示例看起来像这样:

$$
$$  GRID Data
$$
GRID           1        0.0     37.4999819.99999
GRID           2        -13.750233.8154619.99999
GRID           3        130.0   -405.0  39.99871
CHEXA      32662       2   51318   76683   48931   14427   76517   88177
+          55490   48762   51318   76683   48931   14427   76517   88177
+          51318   76683   48931   14427   76517   88177
CHEXA      32663       2   76683   48933   13278   48931   88177   55494
+          17304   55490
CHEXA      32664       2   51311   76677   88177   76517   14422   48924
+          55488   48760
$  PSHELL Data                                                                 
$  PSOLID Data                                                                 
$HWCOLOR PROP                  2       3
PSOLID         2       1       0                                
$HWCOLOR PROP                 14       4
PSOLID        14       1       0                                
$$
$$  MAT1 Data
$$
$  PBAR Data                                                                   
$  MAT1 Data                                                                   
$HMNAME MAT                    1"steel" "MAT1"
$HWCOLOR MAT                   1       3
MAT1           1200000.0        0.3     0.0                             
$$
$$
$$
$$  SPC Data
$$
SPC            1    2656     123     0.0
SPC            1    2697      23     0.0
SPC            1    3239       3     0.0
$$
$$  FORCE Data
$$
FORCE          2    2699       01.0     1000.0  0.0     0.0     
FORCE          3    2699       01.0     0.0     1000.0  0.0     
FORCE          4    2699       01.0     0.0     0.0     1000.0  
FORCE*   29              7928000         102             0.
*       .57735          .57735          .57735
FORCE*   29              7929000         102            16221.9
*       -.0330417       -.0458638       .998401
$ Nodal Forces of Load Set : W06_MZFW_Gust_VB_TMSet102
MOMENT*  30              7906000         102            1.02446+7
*       .188616         .979433         .071665
MOMENT*  30              7907000         102            1.4082+7
*       .966316         .257311         .00498565
$

文本文件中的这些行

CHEXA      32664       2   51311   76677   88177   76517   14422   48924
+          55488   48760
$  PSHELL Data

应该在dict中返回这样的条目:

'CHEXA      32664       2   51311   76677   88177   76517   14422   48924\n+          55488   48760'
pengsaosao

pengsaosao1#

你必须使用调试器,从一个小的正则表达式开始,慢慢地构建它,以确定你错在哪里。

import re
keywords = [ "GRID" , "CHEXA" , "FORCE" , "FORCE*" , "MOMENT" , "MOMENT*"  ]
end_words = [ "GRID" , "CHEXA" , "FORCE" ,  "FORCE*" , "MOMENT" , "MOMENT*" , "$" ]

# Create a regular expression pattern
end_words_pattern = "|".join(f"(^{re.escape(word)})" for word in end_words)

# Read the file
CardsFound = {}
with open("D:/home/bdf_in_test_full.dat", "r") as file:
    file_data = file.read()
    for keyword in keywords:
        pattern = fr"^({re.escape(keyword)} [\s\S]*?)(?={end_words_pattern})"
        matches = re.findall(pattern, file_data, re.MULTILINE | re.DOTALL)
        CardsFound[keyword] = [m[0] for m in matches]

for keyword in keywords:
    print(keyword, ':')
    print(CardsFound[keyword])
    print("\n\n")

编辑基于文件格式的新信息。

搜索到的卡片在下一行具有行继续字符。如果行以+*开头,则它是一个延续行。

import re
keywords = [ "GRID", "CHEXA", "FORCE", "FORCE*", "MOMENT", "MOMENT*" ]

CardsFound = {}
with open("D:/home/bdf_in_test_full.dat", "r") as file:
    file_data = file.read()
    for keyword in keywords:
        pattern = fr"^({re.escape(keyword)} .*?)^(?![+*])"
        matches = re.findall(pattern, file_data, re.MULTILINE | re.DOTALL)
        if matches:
            CardsFound[keyword] = [m.strip() for m in matches]

for keyword in keywords:
    if not keyword in CardsFound: continue
    print(keyword, ':')
    for m in CardsFound[keyword]:
        print(m)
    print("\n")

输出量:

GRID :
GRID           1        0.0     37.4999819.99999
GRID           2        -13.750233.8154619.99999
GRID           3        130.0   -405.0  39.99871

CHEXA :
CHEXA      32662       2   51318   76683   48931   14427   76517   88177
+          55490   48762   51318   76683   48931   14427   76517   88177
+          51318   76683   48931   14427   76517   88177
CHEXA      32663       2   76683   48933   13278   48931   88177   55494
+          17304   55490
CHEXA      32664       2   51311   76677   88177   76517   14422   48924
+          55488   48760

FORCE :
FORCE          2    2699       01.0     1000.0  0.0     0.0
FORCE          3    2699       01.0     0.0     1000.0  0.0
FORCE          4    2699       01.0     0.0     0.0     1000.0

FORCE* :
FORCE*   29              7928000         102             0.
*       .57735          .57735          .57735
FORCE*   29              7929000         102            16221.9
*       -.0330417       -.0458638       .998401

MOMENT* :
MOMENT*  30              7906000         102            1.02446+7
*       .188616         .979433         .071665
MOMENT*  30              7907000         102            1.4082+7
*       .966316         .257311         .00498565
0dxa2lsx

0dxa2lsx2#

使用+以外的任何内容作为结束关键字。

(?ms)^(GRID.+?)^(?!\+)

这里有一个例子,其中 string 是输入数据。

keywords = ['GRID', 'CHEXA', 'FORCE', 'FORCE*', 'MOMENT', 'MOMENT*']

CardsFound = {}

for k in keywords:
    CardsFound[k] = re.findall(rf'(?ms)^({re.escape(k)}.+?)^(?!\+)', string)

for k, v, in CardsFound.items():
    for s in v: print(str.strip(s))
    print()

输出

GRID           1        0.0     37.4999819.99999
GRID           2        -13.750233.8154619.99999
GRID           3        130.0   -405.0  39.99871

CHEXA      32662       2   51318   76683   48931   14427   76517   88177
+          55490   48762   51318   76683   48931   14427   76517   88177
+          51318   76683   48931   14427   76517   88177
CHEXA      32663       2   76683   48933   13278   48931   88177   55494
+          17304   55490
CHEXA      32664       2   51311   76677   88177   76517   14422   48924
+          55488   48760

FORCE          2    2699       01.0     1000.0  0.0     0.0
FORCE          3    2699       01.0     0.0     1000.0  0.0
FORCE          4    2699       01.0     0.0     0.0     1000.0
FORCE*   29              7928000         102             0.
FORCE*   29              7929000         102            16221.9

FORCE*   29              7928000         102             0.
FORCE*   29              7929000         102            16221.9

MOMENT*  30              7906000         102            1.02446+7
MOMENT*  30              7907000         102            1.4082+7

MOMENT*  30              7906000         102            1.02446+7
MOMENT*  30              7907000         102            1.4082+7

编辑

  • ". 1)当搜索关键字“FORCE”时,也会读取以“FORCE*”开头的行中的关键字。..."*

Assert关键字后面的字符不是*

(?ms)^(FORCE(?!\*).+?)^(?!\+)
  • "... 2)以+开头的连续行被正确处理。对于以 * 开头的延续行,也应该发生同样的情况。..."*

您可以将+*放在一个 * 字符类 * 中。

(?ms)^(FORCE(?!\*).+?)^(?![+*])

这里是re-factor。

keywords = ['GRID', 'CHEXA', 'FORCE', 'FORCE*', 'MOMENT', 'MOMENT*']
CardsFound = {}
for k in keywords:
    CardsFound[k] = re.findall(rf'(?ms)^({re.escape(k)}(?!\*).+?)^(?![+*])', string)
for k, v, in CardsFound.items():
    for s in v: print(str.strip(s))
    print()

输出

GRID           1        0.0     37.4999819.99999
GRID           2        -13.750233.8154619.99999
GRID           3        130.0   -405.0  39.99871

CHEXA      32662       2   51318   76683   48931   14427   76517   88177
+          55490   48762   51318   76683   48931   14427   76517   88177
+          51318   76683   48931   14427   76517   88177
CHEXA      32663       2   76683   48933   13278   48931   88177   55494
+          17304   55490
CHEXA      32664       2   51311   76677   88177   76517   14422   48924
+          55488   48760

FORCE          2    2699       01.0     1000.0  0.0     0.0
FORCE          3    2699       01.0     0.0     1000.0  0.0
FORCE          4    2699       01.0     0.0     0.0     1000.0

FORCE*   29              7928000         102             0.
*       .57735          .57735          .57735
FORCE*   29              7929000         102            16221.9
*       -.0330417       -.0458638       .998401

MOMENT*  30              7906000         102            1.02446+7
*       .188616         .979433         .071665
MOMENT*  30              7907000         102            1.4082+7
*       .966316         .257311         .00498565
pkln4tw6

pkln4tw63#

如果你使用rioV8解决方案,它工作正常,只使用re.finditer和re.sub,那么你会得到你想要的。

for keyword in keywords:
    pattern = fr"^({re.escape(keyword)}[\s\S]*?)(?={end_words_pattern})"
    matches = re.finditer(pattern, txt, re.MULTILINE | re.DOTALL)

    for match in matches:
        if match.group():
            print(re.sub(r'\n[+*]', r"", match.group()))
GRID           1        0.0     37.4999819.99999

GRID           2        -13.750233.8154619.99999

GRID           3        130.0   -405.0  39.99871

CHEXA      32662       2   51318   76683   48931   14427   76517   88177          55490   48762   51318   76683   48931   14427   76517   88177          51318   76683   48931   14427   76517   88177

CHEXA      32663       2   76683   48933   13278   48931   88177   55494          17304   55490

CHEXA      32664       2   51311   76677   88177   76517   14422   48924          55488   48760

FORCE          2    2699       01.0     1000.0  0.0     0.0     

FORCE          3    2699       01.0     0.0     1000.0  0.0     

FORCE          4    2699       01.0     0.0     0.0     1000.0  

FORCE*   29              7928000         102             0.       .57735          .57735          .57735

FORCE*   29              7929000         102            16221.9       -.0330417       -.0458638       .998401

FORCE*   29              7928000         102             0.       .57735          .57735          .57735

FORCE*   29              7929000         102            16221.9       -.0330417       -.0458638       .998401

MOMENT*  30              7906000         102            1.02446+7       .188616         .979433         .071665

MOMENT*  30              7907000         102            1.4082+7       .966316         .257311         .00498565

MOMENT*  30              7906000         102            1.02446+7       .188616         .979433         .071665

MOMENT*  30              7907000         102            1.4082+7       .966316         .257311         .00498565

相关问题