Python:re.compile和re.sub

dus*_*her 7 python compare compilation

问题第1部分

我有这个文件f1:

<something @37>
<name>George Washington</name> 
<a23c>Joe Taylor</a23c>
</something @37>
Run Code Online (Sandbox Code Playgroud)

我想重新编译它看起来像这个f1 :(带空格)

George Washington Joe Taylor
Run Code Online (Sandbox Code Playgroud)

我尝试了这段代码,但有点删除了所有内容:

import re
file = open('f1.txt')
fixed = open('fnew.txt','w')
text = file.read()

match = re.compile('<.*>')
for unwanted in text:
    fixed_doc = match.sub(r' ',text)

fixed.write(fixed_doc)
Run Code Online (Sandbox Code Playgroud)

我的猜测是re.compile行,但我不太清楚如何处理它.我不应该使用第三方扩展.有任何想法吗?


问题第2部分

我有一个不同的问题,比较我从Alfe获得此代码的2个文件:

from collections import Counter

def test():
    with open('f1.txt') as f:
        contentsI = f.read()
    with open('f2.txt') as f:
        contentsO = f.read()

    tokensI = Counter(value for value in contentsI.split()
                        if value not in [])
    tokensO = Counter(value for value in contentsO.split()
                        if value not in [])
    return not (tokensI - tokensO) and not (set(tokensO) - set(tokensI))
Run Code Online (Sandbox Code Playgroud)

是否可以在'if value not in []'部分中实现re.compile和re.sub?

eyq*_*uem 26

我将解释您的代码会发生什么:

import re
file = open('f1.txt')
fixed = open('fnew.txt','w')
text = file.read()

match = re.compile('<.*>')
for unwanted in text:
    fixed_doc = match.sub(r' ',text)

fixed.write(fixed_doc)
Run Code Online (Sandbox Code Playgroud)

该指令text = file.read()创建一个名为string的类型的对象文本. 请注意,我使用粗体字符文本来表示OBJECT,并表达此对象的名称== IDENTIFIER. 作为指令的结果,标识符被连续地分配给文本对象引用的每个字符. text
text
for unwanted in text:unwanted

此外,re.compile('<.*>')创建一个RegexObject类型的对象(我个人称之为编译)正则表达式或简单的正则表达式,<.*>只是正则表达式模式).
您将此编译的正则表达式对象分配给标识符match:这是一个非常糟糕的做法,因为match它已经是正则表达式对象的方法的名称,特别是您创建的方法的名称,因此您可以match.match无错误地编写.
match也是re模块的函数名称.
使用此名称满足您的特殊需求非常令人困惑.你必须避免这种情况.

使用file文件f1的文件处理程序作为名称存在同样的缺陷.file已经是语言中使用的标识符,您必须避免使用它.

好.现在,这个坏命名的匹配对象的定义,指令fixed_doc = match.sub(r' ',text)代替全部由正则表达式发现OCCURENCES 比赛的文字与更换r' '.
请注意,编写完全是多余的,r' '而不仅仅是' '因为没有' '必要进行转义.每当他们必须在正则表达式问题中编写字符串时,一些焦虑的人都会写一些原始字符串.

由于<.+>点符号意味着"贪婪地吃掉位于a <和a 之间的每个字符,>除非它是换行符",因此匹配的文本出现的每一行都是直到最后一行>.
由于名称unwanted未出现在此指令中,因此对于文本的每个字符,它是一个接一个地执行的操作.也就是说:没什么好玩的.
要分析程序的执行,您应该在代码中添加一些打印指令,以便了解发生的情况.例如,如果你这样做print repr(fixed_doc),你会看到这样的重复印刷:' \n \n \n '.正如我所说:没有什么有趣的.

您的代码中还有一个默认值:您打开文件,但不关闭它们.关闭文件是强制性的,否则可能会发生一些奇怪的现象,在我意识到这种需要之前,我个人在我的一些代码中观察到了这些现象.有些人假装它不是强制性的,但它是假的.
顺便说一句,打开和关闭文件的更好方式是使用该with语句.它可以完成所有工作而无需担心.

.

那么,现在我可以为您提出第一个问题的代码:

import re

def ripl(mat=None,li = []):
    if mat==None:
        li[:] = []
        return
    if mat.group(1):
        li.append(mat.span(2))
        return ''
    elif mat.span() in li:
        return ''
    else:
        return mat.group()

r = re.compile('</[^>]+>'
               '|'
               '<([^>]+)>(?=.*?(</\\1>))',
               re.DOTALL)

text = '''<something @37>
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c>
</something @37>'''
print '1------------------------------------1'
print text
print '2------------------------------------2'
ripl()
print r.sub(ripl,text)
print '3------------------------------------3'
Run Code Online (Sandbox Code Playgroud)

结果

1------------------------------------1
<something @37>
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c>
</something @37>
2------------------------------------2

George <wxc>Washington 
Joe </zazaza>Taylor

3------------------------------------3
Run Code Online (Sandbox Code Playgroud)

原则如下:

当正则表达式检测到标记时,
- 如果它是结束标记,它匹配 - 如果它是一个开始标记,它只有在文本中某处有相应的结束标记时才
匹配.对于每个匹配,sub()正则表达式的方法r调用该函数ripl()进行更换.
如果匹配是一个开始标记(必须在文本中的某个地方跟随其相应的结束标记,通过构造正则表达式),然后ripl()返回''.
如果匹配带有结束标记,则只有在检测到的文本中此结束标记具有前一个开始标记的相应结束标记时才ripl()返回''.这是通过在列表中记录进行可能的各相应的结束标记的跨度每次检测开始标记时间和匹配的跨度.

记录列表li被定义为默认参数,以便它始终与每次调用函数时使用的列表相同ripl()(请参考undertsand的默认参数的功能,因为它很微妙).
作为li接收默认参数的参数的定义的结果,列表对象li将保留在分析若干文本时记录的所有跨度,以防连续分析若干文本.为了避免列表li保留过去文本匹配的跨度,有必要使列表为空.我编写了函数,以便使用默认参数定义第一个参数None:允许ripl()在正则表达式sub()方法中使用它之前不带参数调用.
然后,ripl()在使用它之前必须考虑写.

.

如果要删除文本的换行符以获得您在问题中显示的精确结果,则必须将代码修改为:

import re

def ripl(mat=None,li = []):
    if mat==None:
        li[:] = []
        return
    if mat.group(1):
        return ''
    elif mat.group(2):
        li.append(mat.span(3))
        return ''
    elif mat.span() in li:
        return ''
    else:
        return mat.group()


r = re.compile('( *\n *)'
               '|'
               '</[^>]+>'
               '|'
               '<([^>]+)>(?=.*?(</\\2>)) *',
               re.DOTALL)

text = '''<something @37>
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c>
</something @37>'''
print '1------------------------------------1'
print text
print '2------------------------------------2'
ripl()
print r.sub(ripl,text)
print '3------------------------------------3'
Run Code Online (Sandbox Code Playgroud)

结果

1------------------------------------1
<something @37>
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c>
</something @37>
2------------------------------------2
George <wxc>WashingtonJoe </zazaza>Taylor
3------------------------------------3
Run Code Online (Sandbox Code Playgroud)