使用python正则表达式从文件中的编号列表获取内容

使用python正则表达式从文件中的编号列表获取内容,python,regex,python-3.x,Python,Regex,Python 3.x,我有以下行的文件: lines.txt 1. robert smith 2. harry 3. john 我想得到如下数组: ["robert\nsmith","harry","john"] 我试过这样的方法: with open('lines.txt') as fh: m = [re.match(r"^\d+\.(.*)",line) for line in fh.readlines()] print(m) for i in m: print(

我有以下行的文件:

lines.txt

1. robert
   smith
2. harry
3. john
我想得到如下数组:

["robert\nsmith","harry","john"]
我试过这样的方法:

with open('lines.txt') as fh:
    m = [re.match(r"^\d+\.(.*)",line) for line in fh.readlines()]
    print(m)
    for i in m:
        print(i.groups())
它的产出如下:

[<_sre.SRE_Match object; span=(0, 9), match='1. robert'>, None, <_sre.SRE_Match object; span=(0, 8), match='2. harry'>, <_sre.SRE_Match object; span=(0, 7), match='3. john'>]
(' robert',)
Traceback (most recent call last):
  File "D:\workspaces\workspace6\PdfGenerator\PdfGenerator.py", line 5, in <module>
    print(i.groups())
AttributeError: 'NoneType' object has no attribute 'groups'
[,无,]
(‘罗伯特’,)
回溯(最近一次呼叫最后一次):
文件“D:\workspaces\workspace6\PdfGenerator\PdfGenerator.py”,第5行,在
打印(i.组())
AttributeError:“非类型”对象没有属性“组”

看来我对这个问题的看法是非常错误的。您将如何解决此问题?

您可以将文件读入内存并使用

r'(?ms)^\d+\.\s*(.*?)(?=^\d+\.|\Z)'

详细信息

  • (?ms)
    -启用
    re.MULTILINE
    re.DOTALL
    模式
  • ^
    -行的开头
  • \d+
    -1+位
  • \。
    -一个点
  • \s*
    -0+空格
  • (.*)
    -第1组(这是
    re.findall
    在此返回的内容):任何0+字符,尽可能少
  • (?=^\d+\.\Z)
    -直到(但不包括)第一次出现
    • ^\d+\。
      -行的开头,1+位和
    • |
      -或
    • \Z
      -字符串结尾
Python:

with open('lines.txt') as fh:
    print(re.findall(r'(?ms)^\d+\.\s*(.*?)(?=^\d+\.|\Z)', fh.read()))

您可以将文件读入内存并使用

r'(?ms)^\d+\.\s*(.*?)(?=^\d+\.|\Z)'

详细信息

  • (?ms)
    -启用
    re.MULTILINE
    re.DOTALL
    模式
  • ^
    -行的开头
  • \d+
    -1+位
  • \。
    -一个点
  • \s*
    -0+空格
  • (.*)
    -第1组(这是
    re.findall
    在此返回的内容):任何0+字符,尽可能少
  • (?=^\d+\.\Z)
    -直到(但不包括)第一次出现
    • ^\d+\。
      -行的开头,1+位和
    • |
      -或
    • \Z
      -字符串结尾
Python:

with open('lines.txt') as fh:
    print(re.findall(r'(?ms)^\d+\.\s*(.*?)(?=^\d+\.|\Z)', fh.read()))

使用
re.findall
查找从
\d\.\s+
模式到下一个'\n\d'模式或直至结束的所有内容

>>> import re
>>> re.findall(r'\d+\.\s+(.*?(?=\n\d|$))', text, flags=re.DOTALL)
['robert\n   smith', 'harry', 'john']

使用
re.findall
查找从
\d\.\s+
模式到下一个'\n\d'模式或直至结束的所有内容

>>> import re
>>> re.findall(r'\d+\.\s+(.*?(?=\n\d|$))', text, flags=re.DOTALL)
['robert\n   smith', 'harry', 'john']

您可以使用
re.split

正则表达式

详情:

  • \n
    -换行符
  • -匹配范围为0到1次,如果存在“新行”,则匹配
  • \d+
    -匹配一个数字(+),匹配次数介于一次和无限次之间
  • \。
    -Dot
  • \s*
    -匹配零次和无限次之间的任何空白字符(等于
    [\r\n\t\f\v]
    )(*)
Python代码

re.split(r'\n?\d+\.\s*', lines)[1:]
[1://code>删除第一项,因为它是空字符串

输出:

['robert\n   smith', 'harry', 'john']

您可以使用
re.split

正则表达式

详情:

  • \n
    -换行符
  • -匹配范围为0到1次,如果存在“新行”,则匹配
  • \d+
    -匹配一个数字(+),匹配次数介于一次和无限次之间
  • \。
    -Dot
  • \s*
    -匹配零次和无限次之间的任何空白字符(等于
    [\r\n\t\f\v]
    )(*)
Python代码

re.split(r'\n?\d+\.\s*', lines)[1:]
[1://code>删除第一项,因为它是空字符串

输出:

['robert\n   smith', 'harry', 'john']

我提出了一个解决方案,只收集名称, 在名字中间没有不必要的空格, 与其他一些解决方案相反

这个想法是:

  • 保存元组列表(编号、名称和段),“正在复制” 前一行中的组号(如果当前行中没有) 线路。要保存的对由getPair函数准备
  • 根据数字(第一个元素)对这些元组进行分组
  • 使用分隔符\n连接每个组中的名称段
  • 将这些连接的名称保存在结果列表中
使用列表理解可以在中编写程序 相当简洁的方式。见下文:

import re, itertools

def getPair(line):
  global grp
  nr, nameSegm = re.match(r'^(\d+\.)?\s+(\w+)$', line).groups()
  if nr:  # Number present
    grp = nr
  return grp, nameSegm   

grp = ''    # Group label (number)
with open('lines.txt') as fh:
  lst = [getPair(line) for line in fh.readlines()]
res = ['\n'.join([t[1] for t in g])
  for _, g in itertools.groupby(lst, lambda x: x[0])]
print(f"Result: {res}")
总而言之,这个程序比其他的稍长一点,但是很简单
只收集名称,不添加空格。

我提出了一个解决方案,只收集
名称, 在名字中间没有不必要的空格, 与其他一些解决方案相反

这个想法是:

  • 保存元组列表(编号、名称和段),“正在复制” 前一行中的组号(如果当前行中没有) 线路。要保存的对由getPair函数准备
  • 根据数字(第一个元素)对这些元组进行分组
  • 使用分隔符\n连接每个组中的名称段
  • 将这些连接的名称保存在结果列表中
使用列表理解可以在中编写程序 相当简洁的方式。见下文:

import re, itertools

def getPair(line):
  global grp
  nr, nameSegm = re.match(r'^(\d+\.)?\s+(\w+)$', line).groups()
  if nr:  # Number present
    grp = nr
  return grp, nameSegm   

grp = ''    # Group label (number)
with open('lines.txt') as fh:
  lst = [getPair(line) for line in fh.readlines()]
res = ['\n'.join([t[1] for t in g])
  for _, g in itertools.groupby(lst, lambda x: x[0])]
print(f"Result: {res}")
总而言之,这个程序比其他的稍长一点,但是很简单
名称,不带空格。

如果
print(i)
您将看到
m[1]
NoneType
,这就是您出现错误的原因。要验证这是否是错误,请尝试运行m[2::::
中的i,您将看到“组”是如何工作的。这并不能回答您的问题。如果您
print(i)
,您将看到
m[1]
NoneType
,这就是您出现错误的原因。要验证这是否是错误,请尝试运行m[2::::
中的i,您将看到“组”是如何工作的。这并不能回答你的问题,你能解释一下吗?特别是
\n?
[1::
你能解释一下吗?尤其是
\n?
[1:][/code>更有效的变体是
(?m)^\d+.\s*(.**:\n(?!\d+\.*))
更有效的变体是
(?m)^\d+.\s*(.**:\n(?!\d+\.*)