首页 > 解决方案 > 使用正则表达式识别包含整个“名称”的文本行(更新问题)

问题描述

注意:这是对我之前的问题的重新发布,并进行了大量的澄清尝试。我希望它更清楚!

我有一个包含一堆行的文件,其中大部分包含我称之为“名称”的内容(一串字母数字字符,可能还有下划线/空格,但没有其他字符),在大多数情况下,=还有一些数字和特殊字符。大多数行都包含一些。有时,“名称”前面有其他字符,例如:or !or others。

更棘手 - 有时“名称”是其他“名称”的子集。例如:

# ignore the line numbers 00| etc.
01| 1 <= foo bar baz = 2 <= 3
02| :NI=5
03| :PENG = 7
04| 42 <= foo = 50 <= 90
05| bar = 27
06| NI PENG NEEWOM = 1000
07| 2 <= PENG2 = 3 <= 4
08| PENG PENG PENG
09| PENG=5
10| NI = 3
11| foo3 bar = 7
12| :fo4o=2

例如,这里foo是第 4 行中的整个“名称”,但不是“名称”所在的第 1 行foo bar baz。同样PENG是第 3 行和第 9 行中的整个“名称”,但不在第 6 行 ( NI PENG NEEWOM)、第 7 行 ( PENG2) 或第 8 行 ( PENG PENG PENG) 中。bar是第 5 行中的整个“名称”,但不是第 1 行 ( foo bar baz) 或第 11 行 ( foo3 bar)。

我希望能够识别给定搜索键是整个“名称”但不是名称一部分的行。同样,“名称”的规则是它是字母数字/下划线/空格字符的连续字符串,但没有其他字符,例如,=等。:!

如果有帮助,在所有相关行中,整个名称后面都会跟一个=.

不需要在一行代码中完成 - 如果需要两个步骤来识别该行然后将其拉出,那很好。

我能想到的问题的另一种方法是将每一行解析为块,拆分使得每个“名称”最终成为一个完整的块,然后将搜索键与整个块匹配:

for line in text:
    chunks = line.split(<any non-alphanumeric/underscore/space character>)
    if key in chunks:
        return True

但这似乎是非常低效的,分割文本中的每一行(我不知道如何分割)。但它得到了这个想法。

标签: pythonregexparsing

解决方案


使用以下带有标志的正则表达式re.I在一行中查找“名称”:

[a-z_][a-z0-9_]*(?: +[a-z_][a-z0-9_]*)*
  1. [a-z_]- 匹配一个字母或下划线字符
  2. [a-z0-9_]*- 匹配 0 个或多个字母数字或下划线字符
  3. (?: +[a-z_][a-z0-9_]*)*-匹配 0 个或多个组:一个或多个空格后跟一个字母或下划线,后跟 0 个或多个字母数字或下划线字符

实际上,“名称”的每个部分都必须以字母或下划线字符(但不是数字)开头。

见正则表达式演示

import re

text = """1 <= foo bar baz = 2 <= 3
 :NI=5
| :PENG = 7
 42 <= foo = 50 <= 90
 bar = 27
 NI PENG NEEWOM = 1000
 2 <= PENG2 = 3 <= 4
 PENG PENG PENG
 PENG=5
 NI = 3
 foo3 bar = 7
 :fo4o=2"""

lines = text.strip().split('\n')

def find(key):
    for line in lines:
        m = re.search(r'[a-z_][a-z0-9_]*(?: +[a-z_][a-z0-9_]*)*', line, re.I)
        if m:
            name = m[0]
            if key == name:
                print(line)
                return True

print(find('NI PENG NEEWOM'))

印刷:

 NI PENG NEEWOM = 1000
True

推荐阅读