【问题标题】:Remove words with spaces or "-" in them Python删除带有空格或“-”的单词Python
【发布时间】:2019-01-20 00:33:18
【问题描述】:

这是问题here的扩展

现在就像在链接的问题中一样,答案使用space? 作为正则表达式模式来匹配带有空格或没有空格的字符串。

问题陈述:

我有一个字符串和一组短语。

input_string = 'alice is a character from a fairy tale that lived in a wonder land. A character about whome no-one knows much about'

phrases_to_remove = ['wonderland', 'character', 'noone']

现在我要做的是从input_string 中删除数组phrases_to_remove 中最后出现的单词。

output_string = 'alice is a character from a fairy tale that lived in a. A about whome knows much about'

注意:要删除的词可能会出现在字符串中,也可能不会出现,如果出现,它们可能以相同的形式出现 {'wonderland' or 'character', 'noone'}或者它们可能在单词之间出现空格或连字符 (-),例如神奇的土地,没有人,性格。

代码的问题是,我无法删除 space- 不匹配的单词。例如 wonder landwonderlandwonder-land

我尝试将(-)?|( )? 用作正则表达式,但无法正常工作。

我需要帮助

【问题讨论】:

  • 您是否在替换列表中尝试过r'\bwonder[ \-]?land\b'
  • @Jean-FrançoisFabre 这是一个正则表达式吗?
  • 这是一个正则表达式。 re.sub(r'\bwonder[ \-]?land\b',"",input_string) 删除单词 all-right(保留单词边界作为奖励)
  • @Jean-FrançoisFabre 这个词 Wonderland 不是硬编码的。要求是删除所有匹配的单词,无论字母之间的 -space 是什么
  • 在这种情况下,您可以在每个字母之间插入空格/破折号,因为您不知道单词何时“中断”

标签: python string


【解决方案1】:

您的正则表达式的问题在于分组。使用(-)?|( )? 作为分隔符并不能达到您认为的效果。

考虑当单词列表为a,b时会发生什么:

>>> regex = "(-)?|( )?".join(["a", "b"])
>>> regex
'a(-)?|( )?b'

您希望此正则表达式匹配 aba ba-b,但显然它不会这样做。它匹配 aa-b<space>b

>>> re.match(regex, 'a')
<_sre.SRE_Match object at 0x7f68c9f3b690>
>>> re.match(regex, 'a-')
<_sre.SRE_Match object at 0x7f68c9f3b718>
>>> re.match(regex, 'b')
<_sre.SRE_Match object at 0x7f68c9f3b690>
>>> re.match(regex, ' b')
<_sre.SRE_Match object at 0x7f68c9f3b718>

要解决此问题,您可以将分隔符包含在其自己的组中:([- ])?

如果您还想匹配wonder - land 之类的单词(即连字符前后有空格),您应该使用以下(\s*-?\s*)?

【讨论】:

    【解决方案2】:

    由于您不知道分隔的位置,您可以生成一个由 ORed 正则表达式组成的正则表达式(使用单词边界来避免匹配子单词)。

    这些正则表达式会在每个字符上使用 str.join 交替单词和 [\s\-]*(匹配零到多次出现的“空格”或“破折号”)的字母

    import re
    
    input_string = 'alice is a character from a fairy tale that lived in a wonder - land. A character about whome no one knows much about'
    
    phrases_to_remove = ['wonderland', 'character', 'noone']
    
    the_regex = "|".join(r"\b{}\b".format('[\s\-]*'.join(x)) for x in phrases_to_remove)
    

    现在处理“替换除第一个匹配项之外的所有内容”部分:让我们定义一个对象,它将替换除第一个匹配项之外的所有内容(使用内部计数器)

    class Replacer:
        def __init__(self):
            self.__counter = 0
    
        def replace(self,m):
            if self.__counter:
                return ""
            else:
                self.__counter += 1
                return m.group(0)
    

    现在将replace 方法传递给re.sub

    print(re.sub(the_regex,Replacer().replace,input_string))
    

    结果:

    alice is a character from a fairy tale that lived in a . A  about whome  knows much about
    

    (生成的正则表达式非常复杂顺便说一句:\bw[\s\-]*o[\s\-]*n[\s\-]*d[\s\-]*e[\s\-]*r[\s\-]*l[\s\-]*a[\s\-]*n[\s\-]*d\b|\bc[\s\-]*h[\s\-]*a[\s\-]*r[\s\-]*a[\s\-]*c[\s\-]*t[\s\-]*e[\s\-]*r\b|\bn[\s\-]*o[\s\-]*o[\s\-]*n[\s\-]*e\b

    【讨论】:

    • OP 只想删除 last 出现的正则表达式。所以你的输出不能满足 Op 的需求。我相信单独re.sub 是行不通的。您需要re.finditer 并仅手动替换最后一次出现...或者:将正则表达式“向后”编写,还原文本并将re.subcount=1 一起使用。
    • 编辑了一个替换函数,使用一个计数器来解决副作用。现在有效。
    【解决方案3】:

    您可以一次使用一个:

    空间:

    对于'-':

    ^[ \t]+
    @"[^0-9a-zA-Z]+
    

    【讨论】:

      猜你喜欢
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多