Python 使用正则表达式上下文替换字符串中的点

Python 使用正则表达式上下文替换字符串中的点,python,regex,Python,Regex,我想删除所有出现的由单个字符分隔的点,我还想用空格替换所有出现的由多个连续字符分隔的点(如果一侧有len>1个字符) 比如说。给定一个字符串 s='A.B.C.D.E。FGH.IJ K.L.M.NO PQ.R.S T.U.VWXYZ' 处理后,输出应如下所示: 'ABCDE FGH IJ荷航无PQ RS TU VWXYZ' 请注意,在A.B.C.D.E.的情况下,所有点都会被删除(当没有尾随点时也应如此) 请注意,在K.L.M.NO的情况下,前两个点被删除,最后一个点被替换为空格(因为NO不是

我想删除所有出现的由单个字符分隔的点,我还想用空格替换所有出现的由多个连续字符分隔的点(如果一侧有len>1个字符)

比如说。给定一个字符串

s='A.B.C.D.E。FGH.IJ K.L.M.NO PQ.R.S T.U.VWXYZ'

处理后,输出应如下所示:

'ABCDE FGH IJ荷航无PQ RS TU VWXYZ'

  • 请注意,在
    A.B.C.D.E.
    的情况下,所有点都会被删除(当没有尾随点时也应如此)
  • 请注意,在
    K.L.M.NO
    的情况下,前两个点被删除,最后一个点被替换为空格(因为NO不是单个字符)
  • 注意,在PQ.R.S
    的情况下,第一个点被替换为空格,第二个点被删除
我几乎有了一个可行的解决方案:

re.sub(r'(?不重要)对于用一个正则表达式来解决这个问题,或者甚至用正则表达式来解决这个问题


编辑:将示例字符串中的
PQ.RS
更改为
PQ.R.S

您可以先用空格替换所有点,然后删除剩余点:

re.sub(r'\.([A-Z]{2})', r' \1', s).replace(".", "")
这为您的示例提供了“ABCDE FGH IJ KLM NO PQ RS TU VWXYZ”

我将采取两个步骤

  • r'\1'
  • r'\1\2'
  • 样品

    进口稀土

    re1 = re.compile(r'(\b[A-Z])\.(?=[A-Z]\b|\s|$)')
    re2 = re.compile(r'(\b[A-Z]{2,})\.(?=[A-Z])|(\b[A-Z])\.(?=[A-Z]{2,})')
    
    s = ' A.B.C.D.E. FGH.IJ K.L.M.NO PQ.RS T.U.VWXYZ'
    
    r = re2.sub(r'\1\2 ', re1.sub(r'\1', s)).strip()
    print(r)
    
    输出

    'ABCDE FGH IJ KLM NO PQ RS TU VWXYZ'
    
    符合您期望的结果:

    'ABCDE FGH IJ KLM NO PQ RS TU VWXYZ'
    
    • re1
      匹配前面有独立字母,后面有另一个独立字母、空格或字符串结尾的所有点
    • re2
      匹配前面至少有2个字母,后面至少有1个字母的所有点(或相反)

      • 希望这稍微整洁一点:

        import re
        
        s = ' A.B.C.D.E. FGH.IJ K.L.M.NO PQ.RS T.U.VWXYZ'
        
        s = re.sub(r"\.(\w{2})", r" \1", s)
        s = re.sub(r"(\w{2})\.(\w)", r"\1 \2", s)
        s = re.sub(r"\.", "",s)
        s = s.strip()
        print(s)
        

        如果您考虑使用动态替换:可以使用单个ReGEX解决方案:

        重新导入
        rx=r'\b([A-Z](?:\[A-Z])+\b(?:\.(?![A-Z])))|\.'
        s='A.B.C.D.E.FGH.IJ K.L.M.无PQ.R.s T.U.VWXYZ'
        打印(re.sub(rx,λx:x.group(1)。如果x.group(1)其他“”,则替换('.',''),s.strip())
        #=>ABCDE FGH IJ荷航无PQ RS TU VWXYZ
        
        请参阅和

        正则表达式匹配:

        • \b([A-Z](?:\[A-Z])+\b(?:\.(?![A-Z]))
          -一个单词边界,然后是组1(在去掉所有句点后将被自身替换)捕获:
          • [A-Z]
            -大写ASCII字母
          • (?:\.[A-Z])+
            -零个或多个点和大写ASCII字母序列
          • \b
            -单词边界
          • (?:\.(?![A-Z])?
            -可选的
            序列,后面不跟大写ASCII字母
        • |
          -或
        • \.
          -任何其他上下文中的
          (将替换为空格)

        lambda x:x.group(1)。如果x.group(1),则替换('.','')否则“”
        replacement意味着,如果组1匹配,则替换字符串为组1值,不带点,如果组1不匹配,则替换为单个规则空格。

        您同意非正则表达式解决方案吗?是的,它不必是正则表达式。非常感谢!尽管我相信在这种情况下这会中断
        s='PQ.R.s
        ,它将给出
        PQRS
        ,而不是预期的
        PQRS
        ,我不确定您的规则是什么,但是您可以使用
        re.sub(r'([a-Z]{2}),r'\1',s)进行第二次传递(在删除点之前)
        ,它用空格替换前面两个字符的点。非常感谢!虽然我相信这会破坏案例
        s='PQ.R.s
        ,它将给出
        PQRS
        ,而不是预期的
        PQ RS
        。我更新了示例以包含此案例。只是注意到您对另一个答案的答复。从您的回答中看不明显estion.Updated完美无瑕。非常感谢