Python:计数项目,将计数存储为变量,用于将字符串替换为外部文件

时间:2015-10-30 15:54:28

标签: regex string python-3.x

我有一组文件,我在其中标记了段落和句子的开头,但我需要迭代每个文件,以便文件中的每个段落和每个句子都有唯一的数字ID。我相信这可以使用str.replace或使用正则表达式模块来完成。

在外部文件中,句子开头标记标记如下:

<p id="####"> # 4 for paragraphs
<s id="#####"> # 5 for sentences

所以在这里我做了调用外部文件并调用段落和句子编号功能(在单独的模块中)的工作,这不起作用。

import re, fileinput, NumberRoutines
ListFiles = ['j2vch34.txt', '79HOch16.txt']

with fileinput.input(files=(ListFiles), inplace=True, backup='.bak') as f:
    for filename in ListFiles:
        with open(filename) as file: 
            text = file.read() # read file into memory
        text = NumberRoutines.NumberParas(text)
        text = NumberRoutines.NumberSentences(text)

    with open(filename, 'w') as file: 
        file.write(text) 

在NumberRoutines中,我尝试应用编号,这是段落的例子:

def NumberParas(text):
    sub = "p id="
    str = text
    totalparas = str.count(sub, 0, len(str))
    counter = 0

    for paranumber in range(totalparas):
        return str.replace('p id="####"', 'p id="{paranumber}"'.format(**locals()))
        counter += 1

根据R Nar的回复,我已经修复了之前的问题,以便我不再收到错误。它重写文件,但是paranumber总是为0。

我尝试应用编号的第二种方式,这次用句子:

def NumberSentences(text):
    sub = "s id="
    str = text
    totalsentences = str.count(sub, 0, len(str))
    counter = 0

    for sentencenumber in range(totalsentences):
        return str.replace('s id="#####"', 's id="{counter}"'.format(**locals()))
        counter += 1

前类型错误(无法将'int'对象隐式转换为str)已解决。

它正在读取和重写文件,但所有句子都被编号为0。

另外两个问题:  1.我是否需要**本地用于for语句中的变量的本地范围?  2.这可以用RegEx完成吗?尽管有很多尝试,但我无法使用{}来替换变量值以使用正则表达式。

我已阅读https://docs.python.org/3.4/library/stdtypes.html#textseq以及Python 3中Mark Summerfields Programming的第13章,并受到Dan McDougall对Putting a variable inside a string (python)的回答的影响

几年前,我在PERL中遇到了同样的事情,2009 Query to PERL beginners,所以感叹。

2 个答案:

答案 0 :(得分:1)

我不知道为什么你有inputfile行,如果你已经要遍历with块内的每个文件,那么我就把它拿出去了

for filename in ListFiles:
    with open(filename) as file: 
        text = file.read()
    text = NumberRoutines.NumberParas(text)
    text = NumberRoutines.NumberSentences(text)
    with open(filename, 'w') as file: 
        file.write(text) # produces error on this line

这使用相同的逻辑。但是,使用您的代码,您的写入块不在for循环中,然后只会写入文件列表中的最后一个文件。

现在有了这些功能:

def NumberParas(text):
    #all that starting stuff can be eliminated with the for loop below
    returnstring = ''
    for i, para in enumerate(text.split('p id="####"')): # minor edit to match spacing in sample.
        if i:
            returnstring = returnstring + 'p id = "%d"%s' % (i-1,para)
        else:
            returnstring = para
    return returnstring

并且类似地:

def NumberSentences(text):
    returnstring = ''
    for i, sent in enumerate(text.split('s id="#####"')): # minor edit to match spacing.
        if i:
            returnstring = returnstring + 's id = "%d"%s' % (i-1,sent) # minor edit for "sent" in this isntance
        else:
            returnstring = sent
return returnstring

我改变逻辑的原因是因为str.replace替换了你想要替换的所有实例,而不仅仅是第一个。这意味着第一次调用它时,所有标签都将在文本中被替换,而for循环的其余部分则无用。另外,你需要实际返回字符串,而不是仅仅在函数中更改它,因为字符串是不可变的,因此你在函数内部的字符串不是你想要改变的真正字符串。

内部if i:行是因为枚举列表中的第一项是第一个标记之前的内容。我认为这将是空的,因为标签在每个句子/段落之前,但你可能有空格或

顺便说一下:这可以通过单线程完成,因为python:

>>> s = 'p tag asdfawegasdf p tag haerghasdngjh p tag aergaedrg'
>>> ''.join(['p tag%d%s' % (i-1, p) if i else p for i,p in enumerate(s.split('p tag'))])
'p tag0 asdfawegasdf p tag1 haerghasdngjh p tag2 aergaedrg'

答案 1 :(得分:1)

  

TypeError:必须是str,而不是None

您的NumberParas(text)不返回任何内容

  

TypeError:无法将'int'对象隐式转换为str

使用int i

str转换为str(i)
  
      
  1. 我是否需要**本地用于for语句中的变量的本地范围?
  2.   

您需要locals () 函数调用来自动构建参数dict。

  
      
  1. 这可以用RegEx完成吗?尽管尝试了很多次,但我无法使用{}来替换变量值以使用正则表达式
  2.   
#!/usr/bin/env python3
import re

tok='####'
regex = re.compile(tok)

bar = 41
def foo(s):
    bar = 42
    return regex.sub("%(bar)i" % locals(), s)

s = 's id="####"'
print(foo(s))

输出:

s id="42"