【问题标题】:Python multiple regular expression replacePython多个正则表达式替换
【发布时间】:2012-02-16 05:16:39
【问题描述】:

我是 python 新手。 我已经搜索了好几天,但只找到了我的一些概念。 Windows 上的 Python 2.7(我选择了 Python,因为它是多平台的,结果可以在 Windows 上移植)。

我想做一个脚本,在文件夹中搜索 *.txt UTF-8 文本文件,加载内容(一个接一个),将非 ascii 字符更改为 html 实体,然后添加 html 标签在每行的开头和结尾,但有 2 种标签变体,一种用于文件的头部,一种用于文件的尾部,它们(head-tail)由空行分隔。之后,所有结果都必须写入另一个文本文件,例如 *.htm。视觉化:

unicode1.txt:

űnícődé text line1
űnícődé text line2
[empty line]
űnícődé text line3
űnícődé text line4

结果必须在 unicode1.htm 中:

<p class='aaa'>&#369;n&iacute;c&#337;d&eacute; text line1</p>
<p class='aaa'>&#369;n&iacute;c&#337;d&eacute; text line2</p>
[empty line]
<p class='bbb'>&#369;n&iacute;c&#337;d&eacute; text line3</p>
<p class='bbb'>&#369;n&iacute;c&#337;d&eacute; text line3</p>

我开始开发解决方案的核心,但我坚持了下来。查看脚本版本(为简单起见,我选择使用 xmlcharrefreplace 进行编码)。

V1:

import re, cgi, fileinput
file="_utf8.txt"
text=""
for line in fileinput.input(file, inplace=0):
  line=cgi.escape(line.decode('utf8'),1).encode('ascii', 'xmlcharrefreplace')
  line=re.sub(r"^", "<p>", line, 1)
  text=text+re.sub(r"$", "</p>", line, 1)
print text

效果很好,但对于这个任务,我认为文件输入不是一种可用的方式。

V2:

import re, cgi, codecs
file="_utf8.txt"
text=""
f=codecs.open(file, encoding='utf-8')
for line in f:
  line=cgi.escape(line,1).encode('ascii', 'xmlcharrefreplace')
  line=re.sub(r"^", "<p>", line, 1)
  text=text+re.sub(r"$", "</p>", line, 1)
f.close()
print text

它弄乱了结果,行的结束标记开始替换第一个字母等。

V3(尝试多行标志):

import re, cgi, codecs
file="_utf8.txt"
text=""
f=codecs.open(file, encoding='utf-8')
for line in f:
  line=cgi.escape(line,1).encode('ascii', 'xmlcharrefreplace')
  line=re.sub(r"^", "<p>", line, 1, flags=re.M)
  text=text+re.sub(r"$", "</p>", line, 1, flags=re.M)
f.close()
print text

同样的结果。

V4(尝试了 1 个正则表达式而不是 2 个):

import re, cgi, codecs
file="_utf8.txt"
text=""
f=codecs.open(file, encoding='utf-8')
for line in f:
  line=cgi.escape(line,1).encode('ascii', 'xmlcharrefreplace')
  text=text+re.sub(r"^(.*)$", r"<p>\1</p>", line, 1)
f.close()
print text

同样的结果。请帮忙。

编辑:我刚刚用十六进制编辑器检查了结果文件,每个结束标记之前都有一个x0D字节!为什么?

Edit2:更改为更合乎逻辑的方法

text+=re.sub(r"^(.*)$", r"<p>\1</p>", line, 1)

Edit3:使用十六进制编辑器,我看到了导致结果混乱的原因:每个 CRLF 之前都有额外的 CR (x0D) 字节。 我追查了 CR 问题,是什么造成的:与 + 的连接

# -*- coding: utf-8 -*-
text=""
f=u"unicode text line1\r\n unicode text line2"
for line in f:
  text+=line
print text

这会导致:

unicode text line1\r\r\n unicode text line2

任何想法,如何解决这个问题?

【问题讨论】:

  • 缩进 4 个空格会创建一个代码块。编辑您的问题,使其更具可读性。
  • 我第一次使用缩进,但错过了每个缩进块之前的空段落。
  • 我不确定我是否真的理解你的问题,我已经尝试了你的最后一个脚本,它似乎得到了你正在寻找的结果,并且结果在浏览器中看起来不错。您能否在结果错误的地方注明您的测试结果?
  • @snim2 对我来说它搞砸了结果:在行首结束标签,删除第一个字母,在行尾什么都没有。如果源代码行是“文本”,我在这里尝试一行来显示结果:ext
  • 为什么需要 line=re.sub(r"^", "

    ", line, 1) text=text+re.sub(r"$", "

    ", 行, 1)?你不能只做连接吗: text += "\n

    " + line + "

    "

标签: python regex replace


【解决方案1】:

这里根本不需要正则表达式,只需这样做:

with open('utf8.txt') as f:
    class_name = 'aaa'
    for line in f:
        if line == '\n':
            classname = 'bbb'
        else:
            # decode / convert line
            line = '<p class="{0}">{1}</p>\n'.format(class_name, line.rstrip())
        # write line to file

您得到的结果看起来不是由正则表达式引起的,因为它们似乎是正确的。问题很可能出在您进行编码/转换的那一行。在不添加标签的情况下打印该行,看看是否符合预期。

【讨论】:

  • 它将在&lt;/p&gt;之前离开换行符
  • @J.F.Sebastian,不错的收获。在答案中添加了rstrip。
  • .rstrip('\n\r') 将在 EOL 时保留 ' \t'。
  • @J.F.Sebastian,我想过,但&lt;p&gt; 中的尾随空格似乎不是很有用。如果 OP 仍然想要您的建议,应该这样做。
  • @Tib,你用我原来的方法没有rstrip吗?如果是这样,请尝试使用 rstrip()
【解决方案2】:
#!/usr/bin/env python
import cgi
import fileinput
import os
import shutil
import sys

def textfiles(rootdir, extensions=('.txt',)):
    for dirpath, dirs, files in os.walk(rootdir):
        for f in files:
            if f.lower().endswith(extensions):
               yield os.path.join(dirpath, f)

def htmlfiles(files):
    for f in files:
        root, _ = os.path.splitext(f)
        newf = root + '.html'
        shutil.copy2(f, newf)
        yield newf

for line in fileinput.input(htmlfiles(textfiles(sys.argv[1])), inplace=True):
    if fileinput.isfirstline():
       klass = 'aaa' # start head part
    line = cgi.escape(line.decode('utf-8').strip())
    line = line.encode('ascii', 'xmlcharrefreplace')
    if not line: # empty line
       klass = 'bbb' # start tail part
       print(line)
    else:
       print('<p class="%s">%s</p>' % (klass, line))

Example

$ python txt2html.py c:\root\dir

【讨论】:

  • 添加了import sys。现在可以工作,但只打印行,我希望将它写到 *.htm 文本文件中。是否有fileoutput 也像fileinput?
  • @Tib:有多个选项,例如,您可以包装textfiles() 以使用shutil.copy2() 复制每个'.txt' 文件,然后将'.html' 文件名生成到文件输入(在此使用inplace=True案子)。或在if fileinput.isfirstline() 中关闭/打开新文件。
  • 我必须调查和学习文档,因为我完全不明白你写的内容 :-) 请记住,我刚开始使用 python :-)
  • @Tib:我添加了htmlfiles() 函数来说明之前的评论。注意:在这种情况下,数据被读/写两次。
  • @Tib: shutil.copy 读取.txt 文件,写入.html 文件; fileinput.input() 读取 .html,写入 .html:总共 4 次。
猜你喜欢
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多