【问题标题】:Replace a specific word given its position in a text file (Python)给定文本文件中的位置替换特定单词(Python)
【发布时间】:2016-04-27 16:21:50
【问题描述】:

我有一个元组列表,每个元组都包含一个要替换的单词,它来自给定文本文件的行号和列号位置。我想浏览文本文件并用字符替换该特定位置的特定单词(例如[('word1', 1, 1), ('word2', 1, 9), ... ])。

换句话说,给定一个特定的单词,它在文本文件中的行号和列号我试图找到并用一个字符替换该单词,例如:

鉴于文本文件包含以下内容(假设它的位置与显示的一样 - 未写入 - 此处

现在他很兴奋,自然而然地看到了你更分钟的通道。按堆栈 成为法庭的希望。更远的是朋友们要减损。禁止关注 做私人。得罪住处,但男人全神贯注害羞。假装我 堆栈 认真到达公司等等。费利西蒂知道但必须是 严格承认你是如何堆叠的。

假设要替换的单词是stack,在文本中的位置是3 和列16,用字符* 替换它,

因此,在替换发生后,文本文件现在将包含以下内容:

现在他很兴奋,自然而然地看到了你更分钟的通道。按堆栈 成为法庭的希望。更远的是朋友们要减损。禁止关注 做私人。得罪住处,但男人全神贯注害羞。假装我 * 认真到公司等等。费利西蒂知道但必须是 严格承认你是如何堆叠的。

我考虑过linecache,但对于大型文本文件来说似乎效率很低。另外,鉴于我已经有了行号和列号,我希望有一种方法可以直接转到该位置并执行替换。

有谁知道在 Python 中执行此操作的方法?

编辑

使用 numpy 的genfromtxt 提出的初始解决方案(很可能)不适合在后续issue 的讨论之后,因为需要文本文件的每一行都存在而不是跳过(例如空行、以 'w' 开头的字符串和 '/*.. /' 内的字符串)。

【问题讨论】:

  • 看看这个answer 它可以帮助您阅读特定的行,但您必须遍历整个文件。

标签: python python-3.x


【解决方案1】:

试试这样的食谱:

import numpy as np
import os

def changethis(pos):
    # Notice file is in global scope
    appex = file[pos[1]-1][:pos[2]] + '*' + file[pos[1]-1][pos[2]+len(pos[0]):]
    file[pos[1]-1] = appex

pos = ('stack', 3, 16)
file = np.array([i for i in open('in.txt','r')]) #BEFORE EDIT: np.genfromtxt('in.txt',dtype='str',delimiter=os.linesep)
changethis(pos)
print(file)

结果是这样的:

[ 'Excited him now natural saw passage offices you minuter. At by stack being court hopes. Farther'
 'so friends am to detract. Forbade concern do private be. Offending residence but men engrossed'
 'shy. Pretend am * earnest arrived company so on. Felicity informed yet had to is admitted'
 'strictly how stack you.']

请注意,将一堆长字符串放入 numpy 数组中并以某种方式更改它们有点像 hack,但在为位置元组插入更长的循环时应该是有效的。

编辑:@user2357112 让我意识到文件阅读器的选择不是最合适的(尽管它适用于相关练习),所以我编辑了这个答案以提供相同的答案the follow up question中给出的解决方案。

【讨论】:

  • 努力理解这是做什么的;你能解释一下changethis的方法吗?
  • @hask.duk 该函数正在读取您给出的位置并将字符串分成两部分:单词之前的所有内容,以及单词之后的所有内容(那些带有位置的索引)。然后它会构建一个新字符串,将这两个部分连接起来,并在中间添加一个“*”。之后,元素在 numpy 数组中被完全替换。
  • 有兴趣的可以看看这个follow-up question
  • @hask.duk 很抱歉使用 genfromtxt。我只是试图根据您在问题中提供的练习给出一个解决方案。无论如何,我注意到另一个问题引起了很多关注。如果您可能感兴趣,我会跟进这个解决方案(以某种方式基于 numpy)。
  • 感谢您再次查看此内容。一开始我的描述应该更明确。
【解决方案2】:

考虑一行:

word1一个word2一个word3一个word4

如果你有这些变化:

[('word1', 1, 1), ('word2', 1, 9), ... ]

然后你按顺序处理它们:

* 一个词2 一个词3 一个词4

你会失败,因为当你用更短的字符串 '*' 替换 'word1' 时,你正在改变单词的位置。

相反,您必须按行对更改列表进行排序,按列反转:

changes = sorted(changes, key=lambda t: (t[1], -t[2]))

然后,您可以在遍历文件时处理更改,如@JRajan 引用的链接所示:

with open("file", "r") as fp:
    fpline_text = enumerate(fp)
    fpline,text = next(fpline_text)

    for edit in changes:
        word,line,offset = edit
        line -=1  # 0 based

        while fpline < line:
            print(text)
            fpline,text = next(fpline_text)

        offset -= 1    # 0-based
        cand = text[offset:offset+len(word)]

        if cand != word:
            print("OOPS! Word '{}' not found at ({}, {})".format(*edit))
        else:
            text = text[0:offset]+'*'+text[offset+len(word):]

    # Rest of file
    try:
        while True:
            print(text)
            fpline,text = next(fpline_text)
    except StopIteration:
        pass

【讨论】:

  • 在实现排序部分时遇到问题:changes = [('word1', 1, 1), ('word2', 1, 9), ('word2', 1, 12)]changes = sorted(changes, key=lambda t: return (t[0], t[1], -t[2])) 给了我return outside of function error。我做错了吗?
  • 建议进行编辑以处理代码错误并进行修改以匹配预期的描述。
  • 我修改了这个例子。 lambda 应该只包含一个表达式,而不是一个返回值: lambda t: (t[1],-t[2])
猜你喜欢
  • 2020-04-15
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多