使用python从文本文件中的特定模式中提取文本

问题描述 投票:0回答:3

我有一个文本文件,我试图从中提取标题到 Excel 列。但是,所需的标题符合特定模式:

COM *******************
COM * Title 1*
COM *******************

COM ***************************
COM * Sub 1 *
COM ***************************
{
...TEXT DETAILS...
}
COM ***************************
COM * Sub 2 *
COM ***************************
{
...TEXT DETAILS...
}


COM *******************
COM * Title 2*
COM *******************

COM ***************************
COM * T2 Sub 1  *
COM ***************************
{
...TEXT DETAILS...
}
COM ***************************
COM * T2 Sub 2 *
COM ***************************
{
...TEXT DETAILS...
}

字符串提取(标题)所需输出格式为:

['Title 1', 'Sub 1',..,'T2 Sub 2']

或 excel 列为

CATEGORY
Title 1
Sub 1
Sub 2

Title 2
T2 Sub 1
T2 Sub 2

实际上是“COM *****”模式和由我无法实现的标题组成的中线。我最近根据字符串模式提取了所需的字符串,我认为这与我当前的问题类似。

对于这种情况,i/p 文本文件采用以下格式:

CTG 'GEN:LT'                               
{
TEXT DETAILS....
}

CTG 'GEN:FR'                               
{
TEXT DETAILS....
}

CTG 'GEN:G_L02'                                
{
TEXT DETAILS....
}

CTG 'GEN:ER'                               
{
TEXT DETAILS....
}

CTG 'GEN:C1' 
{
TEXT DETAILS....
}

我的目标是提取' '中的CTG之后的字符串 我的想法是检测 CTG 字符串并打印它旁边的字符串。这是我实现相同方法的方法:

import re
def getCtgName(text):     
  matches = re.findall(r"'(.+?)'",text)
  return matches

mylines = []                                # Declare an empty list.
with open ('filepath.txt', 'rt') as myfile:    # Open .txt for reading text.
    for myline in myfile:                   # For each line in the file,
        mylines.append(myline.rstrip('\n')) # strip newline and add to list.

columns = []
substr = "CTG"                  # substring to search for.
for line in mylines:            # string to be searched
  if substr in line:
     columns.append(getCtgName(line)[0])
print(columns)
  

得到的输出为:

['GEN:LT', 'GEN:FR',..., 'GEN:C1']

我相信可以为这些注释(COM****)行之间的Title提取实现类似的逻辑,任何有关代码或逻辑或资源的帮助将不胜感激。谢谢!

python excel regex text
3个回答
0
投票

我假设标题不会包含

*
字符。

import re

headings = []

# Assuming that each line from the text file is already read and stored in a list named 'strings'
for string in strings:
    sub_string = re.search('COM \*([^*]+)\*', string)
    if sub_string:
        headings.append(sub_string.group(1).strip())

输入:

strings = [
    'COM *******************',
    'COM * Title 1*',
    'COM *******************',
    'COM ***************************',
    'COM * Sub 1 *',
    'COM ***************************',
    '{',
    '...TEXT DETAILS...',
    '}',
    'COM ***************************',
    'COM * Sub 2 *',
    'COM ***************************',
    '{',
    '...TEXT DETAILS...',
    '}',
    'COM *******************',
    'COM * Title 2*',
    'COM *******************',
    'COM ***************************',
    'COM * T2 Sub 1  *',
    'COM ***************************',
    '{',
    '...TEXT DETAILS...',
    '}',
    'COM ***************************',
    'COM * T2 Sub 2 *',
    'COM ***************************',
    '{',
    '...TEXT DETAILS...',
    '}',
]

输出:

['Title 1', 'Sub 1', 'Sub 2', 'Title 2', 'T2 Sub 1', 'T2 Sub 2']

0
投票

我认为您可以使用lookbehind和lookahead将这段代码简化为一个正则表达式模式。这两种技术允许您指定必须在比赛之前或之后出现但不包含在比赛本身中的特定部分。语法为

(?<=text)
表示后视,
(?=text)
表示前视。

因此,标题之前的部分是

COM ***************************\nCOM *
,标题后面的部分是
*\nCOM ***************************
。当我们将其放入正则表达式语法中时,模式为:
(?<=COM \*{27}\nCOM \*)[^\n]+(?=\*\nCOM \*{27})

在Python代码中,变成:

import re

with open ('filepath.txt', 'rt') as myfile:
    txt=myfile.read()

pattern=r"(?<=COM \*{27}\nCOM \*)[^\n]+(?=\*\nCOM \*{27})"
titles=re.findall(pattern,txt)

执行此操作的另一种方法是首先使用您的代码,然后删除结果中所有出现的“****************************” .

实施:

import re
def getCtgName(text):     
  matches = re.findall(r"'(.+?)'",text)
  return matches

mylines = []                                # Declare an empty list.
with open ('filepath.txt', 'rt') as myfile:    # Open .txt for reading text.
    for myline in myfile:                   # For each line in the file,
        mylines.append(myline.rstrip('\n')) # strip newline and add to list.

titles = []
substr = "CTG"                  # substring to search for.
for line in mylines:            # string to be searched
  if substr in line:
     titles.append(getCtgName(line)[0])

while "*"*27 in titles:
    titles.remove("*"*27)

print(titles)

0
投票

只需使用以下正则表达式而不是函数 getCtgName 中的正则表达式,假设标题和主题不会将 * 作为值:

matches = re.findall(r"COM\s*\*([^*]+)", text)
© www.soinside.com 2019 - 2024. All rights reserved.