【问题标题】:Concatenate the term using substitute method via regex通过正则表达式使用替换方法连接术语
【发布时间】:2021-06-08 04:57:48
【问题描述】:

问题总结: 我已经编写了通用正则表达式来从句子中捕获两个组。此外,我需要将第 2 组的第 3 项连接到第 1 组。我在正则表达式中使用了and 这个词作为分区来分隔两组句子。例如:

Input = '因为SAC-1和RbC-27的遗传细胞合成不是由人脸和动物皮肤痤疮的WbC-2引起的。 '

Output = '因为SAC-1合成和RbC-27合成的基因细胞不是由人脸痤疮的WbC-2引起的皮肤和动物皮肤。'

我尝试过的正则表达式:

import re
string_ = "Since, the genetic cells of SAC-1 and RbC-27 synthesis was not caused by WbC-2 of acnes in human face and animals skin." 
regex_pattern = re.compile(r"\b([A-Za-z]*-\d+\s*|[A-Za-z]+\s*)\s+(and\s*[A-Za-z]*-\d+\s*[A-Za-z]*|and\s*[A-Za-z]+\s*[A-Za-z]+)?")
print(regex_pattern.findall(string_))
print(regex_pattern.sub(lambda x: x.group(1) + x.group(2)[2], string_))

正则表达式能够捕获组,但我在 substitute 方法行中收到错误为 TypeError: 'NoneType' object is not subscriptable。任何形式的建议或帮助执行上述问题将不胜感激。

【问题讨论】:

  • 欢迎来到 StackOverflow。在新问题方面,这写得很好,干得好!但是,当您写“我遇到错误”时,这表明您应该包含该错误。程序是否因错误而退出?如果是这样,请在此处复制并粘贴错误消息。或者你只是得到错误的输出。如果是这种情况,请尝试提供输出,以便用户可以尝试了解问题所在,而无需先尝试代码。
  • @Kraigolas 感谢您的建议。我已经编辑了问题并包含了我遇到的错误。

标签: python regex string regex-group python-re


【解决方案1】:

拆分解决方案

虽然这不是正则表达式解决方案,但它确实有效:

from string import punctuation

x = 'Since, the genetic cells of SAC-1 and RbC-27 synthesis was not caused by WbC-2 of acnes in human face and animals skin.'
x = x.split()
for idx, word in enumerate(x):
    if word == "and":
        # strip punctuation or we will get skin. instead of skin
        x[idx] = x[idx + 2].strip(punctuation) + " and"
print(' '.join(x))

输出是:

由于人脸皮肤和动物皮肤中痤疮的WbC-2不是导致SAC-1合成和RbC-27合成的遗传细胞。

此解决方案避免直接插入到列表中,因为这会在您迭代时导致索引出现问题。相反,我们将列表中的第一个“and”替换为“synthesis and”,将第二个“and”替换为“skin and”,然后重新加入拆分字符串。

正则表达式解决方案

如果您坚持使用正则表达式解决方案,我建议将re.findall 与包含 single 和 的模式一起使用,因为这更适用于问题:

from string import punctuation
import re
pattern = re.compile("(.*?)\sand\s(.*?)\s([^\s]+)")
result = ''.join([f"{match[0]} {match[2].strip(punctuation)} and {match[1]} {match[2]}" for match in pattern.findall(x)])
print(result)

由于人脸皮肤和动物皮肤中痤疮的WbC-2不是导致SAC-1合成和RbC-27合成的遗传细胞。

我们再次使用strip(punctuation),因为skin. 被捕获:我们不想在句子的end 处丢失标点符号,但我们确实希望在句子中丢失它.

这是我们的模式:

(.*?)\sand\s(.*?)\s([^\s]+)
  1. (.*?)\s:捕获“and”之前的所有内容,包括空格
  2. \s(.*?)\s:捕捉紧跟在“and”之后的单词
  3. ([^\s]+):捕获直到下一个空格之前不是空格的任何内容(即“and”之后的第二个单词)。这样可以确保我们也能捕捉到标点符号。

【讨论】:

  • 这两种解决方案都很棒,也适用于一般情况。非常感谢兄弟。同样在 30 分钟内,我从你那里学到了一些东西。
【解决方案2】:

你不需要导入punctuation,一个正则表达式就可以了:

import re
x = 'Since, the genetic cells of SAC-1 and RbC-27 synthesis was not caused by WbC-2 of acnes in human face and animals skin.'
pattern = re.compile(r"(.*?)\s+and\s+(\S+)\s+(\S+)\b([_\W]*)", re.DOTALL)
result = ''.join([f"{a} {c} and {b} {c}{d}" for a,b,c,d in pattern.findall(x)])
print(result)

结果Since, the genetic cells of SAC-1 synthesis and RbC-27 synthesis was not caused by WbC-2 of acnes in human face skin and animals skin.

Python proof

使用re.DOTALL 允许点匹配换行符。
在末尾使用\b 字边界去除标点符号并将其捕获到一个单独的组中([_\W]*)
使用 \s+ 从结果中修剪任意数量的空白字符。
[^\s]\S 相同,请缩短。

regex proof

解释

--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    .*?                      any character (0 or more times (matching
                             the least amount possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  \s+                      whitespace (\n, \r, \t, \f, and " ") (1 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  and                      'and'
--------------------------------------------------------------------------------
  \s+                      whitespace (\n, \r, \t, \f, and " ") (1 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    \S+                      non-whitespace (all but \n, \r, \t, \f,
                             and " ") (1 or more times (matching the
                             most amount possible))
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  \s+                      whitespace (\n, \r, \t, \f, and " ") (1 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (                        group and capture to \3:
--------------------------------------------------------------------------------
    \S+                      non-whitespace (all but \n, \r, \t, \f,
                             and " ") (1 or more times (matching the
                             most amount possible))
--------------------------------------------------------------------------------
  )                        end of \3
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  (                        group and capture to \4:
--------------------------------------------------------------------------------
    [_\W]*                   any character of: '_', non-word
                             characters (all but a-z, A-Z, 0-9, _) (0
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \4

【讨论】:

  • 感谢您的解决方案。您的正则表达式正在运行,但在 .join 方法中需要进行一些小的更改,因为例如句子 However, the gene of acne and non-acne patients was not affected by cancer. .join 方法在两者之间终止,并且不考虑输出结果中句子的其他部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 2012-07-04
  • 1970-01-01
相关资源
最近更新 更多