Python:使用正则表达式捕获模式内的子模式

3

免责声明:这是我的第一篇帖子。欢迎给我反馈,告诉我应该或不应该如何格式化此问题。谢谢!

我想从文本块中提取数据,通过捕获与日期格式后跟冒号匹配的任何内容来实现。我已成功使用正则表达式捕获信息,包括观察日期、冒号以及在下一个日期之前的句点之前跟随的任何文本。

例如:
1999-01-01: 观察到10只鸟。

我遇到的问题是,我的一些数据包含观测日期后跟随的观测数据中的站点名称和冒号。这个“站点名:数据”的子模式可能在以下块中出现零次或多次。观察日期后面的块。

例如:
1999-01-01: BS-001:观察到5只鸟。全部健康。BS-002:观察到5只鸟,其中一些健康状况不佳。

我应该使用什么模式来捕获日期格式和冒号之后的所有文本,包括潜在的站点名称、它们的冒号和相关数据,直到下一个观察日期之前的句点?

我目前使用以下模式按日期和观察提取简单的观测数据(不包含多个站点):

pattern = re.compile(r'(\d\d\d\d\-*\s*\&*\d+\-*\d*:[A-Za-z0-9\s\,\(\)\;\"\-]*\.*)')  

上面的代码让我可以提取出以各种形式呈现的观测日期。由于观测数据可能是一个或多个句子,所以在模式中使用句点很棘手。
以下是我尝试搜索和分离的文本示例。每个新匹配项都应以观察日期开头,在下面的数据中应返回3个匹配项(2013-04-13:数据,2017-01-01:数据和2018-07-04:数据):
理想情况下,输出应如下所示:
2013-04-13: BS-440: 在春季池栖息地观察到10个卵块。观察员注意到AMJE的3个质地坚硬的卵块类似于3周大的AMMA卵块,但外面更“崎岖”(卵块中的膜和胚胎间距类似于AMJE)。BS-443:在春季池栖息地观察到3个卵块。由于光线不好,可能漏掉了一些卵块。Smith-019:在春季池栖息地观察到250个卵块。观察员仅搜索了和路(池的SW边缘)相邻的部分。许多AMJE卵块附着在草本植物上,难以相互区分。AMJE卵块计数是在搜索区域内的粗略估计。
2017-01-01: 观察到23个个体。没有发现卵块。
2018-07-04: BS-440: 所有个体都休息了一个漫长的周末,没有进行繁殖。
4个回答

2
您可以尝试将所有空格加日期的部分替换为两个换行符:
s = re.sub(r'\s+(?=\d{4}-*\s*&*\d+-*\d*:)', "\n\n", s)

这样,您就不会在字符串开头匹配第一个日期。

如果您不确定每个日期前面是否有空格,也可以这样写:

s = re.sub(r'\s*(?!^)(?=\d{4}-*\s*&*\d+-*\d*:)', "\n\n", s)

2

基本上,您想将文本分成以日期开头并在日期或文本结束之前结束的字段。以下是一种可能的方法:

\d{4}-\d\d-\d\d:           # date with colon
.*?                        # the minimal amount of any characters required to match
(?=                        # positive lookahead (match text but don't consume it)
   \d{4}-\d\d-\d\d:        # date with colon
  |                        # or
   $                       # end of text
)                          # end lookahead

re.findall()一起使用:

findall(r'\d{4}-\d\d-\d\d:.*?(?=\d{4}-\d\d-\d\d:|$)', mytext)

对上面的样本文本进行运行:

['2013-04-13: BS-440: 10 egg masses observed in vernal pool habitat.
  Observer noted 3 of the AMJE masses had firm jelly, akin to a 3-wk
  old AMMA mass, but "bumpier" on outside (membrane and embryo-spacing
  in the masses were AMJE-like). BS-443: 3 egg masses observed in
  vernal pool habitat. A few egg masses may have been missed due to
  poor light conditions. Smith-019: 250 egg masses observed in
  vernal pool habitat. Observer searched only portions abutting the 
  road (SW margin of pool). Many AMJE masses observed attached
  to herbaceous vegetation and difficult to differentiate from
  one another. AMJE egg-mass count is a rough estimate within
  area searched. ',
 '2017-01-01: 23 individuals observed. Egg masses were not present. ',
 '2018-07-04: BS-440: All individuals took a break from breeding for
  the long holiday weekend.']

谢谢,这里有几个很好的解决方案,但是你的解决方案包括了一个解释,帮助我更好地理解正则表达式符号。谢谢! - MrChancey

2

1
聪明,我没有想到要按日期模式拆分,但这很有道理,因为它相当一致。 - MrChancey

1
你可以使用pattern.split:

pattern = re.compile(r'(\d{4}-\d{2}-\d{2})')
parts = pattern.split(string)

这个句子的意思是:“这将产生”。
['', '2013-04-13', ': BS-440: 10 egg masses observed...', ...]

如果pattern包含捕获括号,则其内容与输入字符串的分割部分交错。因为字符串的开头匹配了一个日期,所以第一部分为空。因此,''.join(parts[1:3])产生第一个条目,以此类推。

1
谢谢,如果我最终将它们放入带有日期字段和生物数据字段的表中,将数据拆分成这些部分可能会非常有用。 - MrChancey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接