换行后的负向前瞻?

3 投票
4 回答
1581 浏览
提问于 2025-04-15 14:19

我有一个类似CSV格式的文本文件,大约有1000行。在文件中的每条记录之间,有一长串的破折号。记录通常以一个换行符(\n)结束,但有时在记录结束前会多出一个换行符。下面是一个简化的例子:

"1x", "1y", "Hi there"
-------------------------------
"2x", "2y", "Hello - I'm lost"
-------------------------------
"3x", "3y", "How ya
doing?"
-------------------------------

我想把多出来的换行符替换成空格,也就是把破折号之间的行连接起来。我原以为可以这样做(使用Python 2.5):

text = open("thefile.txt", "r").read()    
better_text = re.sub(r'\n(?!\-)', ' ', text)

但是这样似乎把每个换行符都替换了,而不仅仅是那些后面没有破折号的换行符。我哪里出错了呢?

我提这个问题是想提高自己的正则表达式技能,理解我犯的错误。最终目标是生成一个文本文件,这个文件的格式可以被一个特定的VBA宏使用,这个宏会生成一个样式化的Word文档,然后这个文档会被一个适合Word的内容管理系统处理。

4 个回答

1
re.sub(r'(?<!-)\n(?!-)', ' ', text)

(连字符在字符类外部不需要转义。)

7

这里是一个很好的地方,可以使用生成器函数来跳过那些----的行,并输出一些csv模块可以读取的内容。

def readCleanLines( someFile ):
    for line in someFile:
        if line.strip() == len(line.strip())*'-':
            continue
        yield line

reader= csv.reader( readCleanLines( someFile ) )
for row in reader:
    print row

这样可以轻松且安静地处理引号内的换行符。


如果你想对这个文件做其他事情,比如保存一个去掉----行的副本,你可以这样做。

with open( "source", "r" ) as someFile:
    with open( "destination", "w" ) as anotherFile:
        for line in readCleanLines( someFile ):
            anotherFile.write( line )

这样会生成一个去掉----行的副本。不过其实这样做并不太值得,因为读取和跳过这些行的速度非常快,而且不需要额外的存储空间。

5

你需要去掉分隔线末尾的换行符。试试这个:

\n(?<!-\n)(?!-)

这个正则表达式使用了一种叫做“负向前瞻”的技巧,来排除那些前面有一个-\n换行符。

撰写回答