【问题标题】:Regular expression to remove line breaks正则表达式删除换行符
【发布时间】:2011-07-01 19:22:48
【问题描述】:

我是 Python 的新手,但遇到了一个正则表达式问题。我正在尝试删除文本文件中每行末尾的换行符,但前提是它遵循小写字母,即[a-z]。如果行尾以小写字母结尾,我想用空格替换换行符/换行符。

这是我目前得到的:

import re
import sys

textout = open("output.txt","w")
textblock = open(sys.argv[1]).read()
textout.write(re.sub("[a-z]\z","[a-z] ", textblock, re.MULTILINE) )
textout.close()

【问题讨论】:

  • 如果RE中没有$^,则不需要标签re.MULTILINE

标签: python regex python-2.7


【解决方案1】:

我的观点是,避免使用正面的lookbehind 可能会使代码更具可读性

好的。不过,就我个人而言,我认为它的可读性并不低。这是一个品味问题。

在您的编辑中:

  • 首先,(?m) 不是必需的,因为 for line in ifp: 一次选择一行,因此在每行字符串的结尾

  • 其次,$ 放置后没有实用性,因为它总是匹配字符串行的结尾。

无论如何,采用您的观点,我找到了两种避免后向断言的方式:

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            ante_newline,lower_last = re.match('(.*?([a-z])?$)',line).groups()
            ofp.write(ante_newline+' ' if lower_last else line)

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            ofp.write(line.strip('\r\n')+' ' if re.search('[a-z]$',line) else line)

第二个更好:只有一行,简单的匹配测试,不需要groups(),自然逻辑

编辑:哦,我意识到这第二个代码只是您在一行中重写的第一个代码,Longair

【讨论】:

    【解决方案2】:

    作为替代答案,虽然它需要更多的行,但我认为以下可能更清楚,因为正则表达式更简单:

    import re
    import sys
    
    with open(sys.argv[1]) as ifp:
        with open("output.txt", "w") as ofp:
            for line in ifp:
                if re.search('[a-z]$',line):
                    ofp.write(line.rstrip("\n\r")+" ")
                else:
                    ofp.write(line)
    

    ... 这样可以避免将整个文件加载到字符串中。如果您想使用更少的行,但仍要避免后视,您可以这样做:

    import re
    import sys
    
    with open(sys.argv[1]) as ifp:
        with open("output.txt", "w") as ofp:
            for line in ifp:
                ofp.write(re.sub('(?m)([a-z])[\r\n]+$','\\1 ',line))
    

    该正则表达式的部分是:

    • (?m) [开启多行匹配]
    • ([a-z]) [匹配单个小写字符作为第一组]
    • [\r\n]+ [匹配一个或多个回车符或换行符,以覆盖\n\r\n\r]
    • $ [匹配字符串结尾]

    ...如果匹配行,小写字母和行尾被替换为\\1,这将是小写字母后跟一个空格。

    【讨论】:

    • 一行ofp.write(re.sub("(?<=[a-z])(\n|\r\n?)"," ",line)而不是四行
    • @eyquem:当然,但我的意思是,避免使用正面的后视可能会使代码更具可读性,并且三行额外的行可能是值得的......好吧,我会添加另一个无论如何都是版本。
    【解决方案3】:

    试试

    re.sub(r"(?<=[a-z])\r?\n"," ", textblock)
    

    \Z 只匹配字符串的末尾,在最后一个换行符之后,所以这里绝对不是你需要的。 \z 无法被 Python 正则表达式引擎识别。

    (?&lt;=[a-z]) 是一个positive lookbehind assertion,用于检查当前位置之前的字符是否为小写 ASCII 字符。只有这样,正则表达式引擎才会尝试匹配换行符。

    此外,始终使用带有正则表达式的原始字符串。使反斜杠更易于处理。

    【讨论】:

    • 我会将\r?\n 替换为[\r\n]+ 以同时点击单个\r
    • @ThiefMaster,顺便说一句,它也会去掉空行
    • @ThiefMaster:周围还有使用\r 的Mac,Python 可以在它们上面运行吗?我以为 Apple 放弃了 OS X 的 \r 行结尾,但我可能完全错了。
    • 希望不是......但你永远不知道周围有哪些糟糕的文件 - 包含\n\r\n混合的文件太多了,所以我希望有一些\r文件也仍然存在。
    • 所以[\r\n]{1,2} 会做,或者根据我的说法更好:(\n|\r\n?) 其中\r 的可能性是第三个要测试的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    相关资源
    最近更新 更多