用Python在文件中间插入行?

tkb*_*kbx 50 python

有没有办法做到这一点?假设我有一个文件列表,其名称如下:

  1. 阿尔弗雷德
  2. 法案
  3. 唐纳德

如何在第x行(在本例中为3)插入第三个名称"Charlie",并自动将所有其他名称下移一行?我见过这样的其他问题,但他们没有得到有用的答案.可以这样做,最好是用方法还是循环?

mar*_*cho 68

这是一种做法的方法.

f = open("path_to_file", "r")
contents = f.readlines()
f.close()

contents.insert(index, value)

f = open("path_to_file", "w")
contents = "".join(contents)
f.write(contents)
f.close()
Run Code Online (Sandbox Code Playgroud)

"index"和"value"是您选择的行和值,行从0开始.

  • 使用`f.writelines(内容)`而不是自己加入它不是更简单吗? (8认同)
  • 这可能比我的回答更清晰,但你可以避免打开和关闭文件两次. (4认同)
  • .join条件有什么用? (2认同)

Dav*_*idS 19

如果要在文件中搜索子字符串并将新文本添加到下一行,则执行此操作的优雅方法之一如下:

import fileinput
for line in fileinput.FileInput(file_path,inplace=1):
    if "TEXT_TO_SEARCH" in line:
        line=line.replace(line,line+"NEW_TEXT")
    print line,
Run Code Online (Sandbox Code Playgroud)

  • 在python3上,`print(line,end ='')`对于不在行之间插入额外的换行符很有用. (4认同)
  • 谁能解释一下这是如何工作的?print() 函数如何将其输出流式传输到文件?谢谢! (2认同)

Sea*_*ean 8

接受的答案必须将整个文件加载到内存中,这对于大文件来说效果不佳。以下解决方案将文件内容以及插入到右行的新数据写入同一目录中的临时文件(因此在同一文件系统上),一次仅从源文件中读取小块。然后,它以有效的方式用临时文件的内容覆盖源文件(Python 3.8+)。

from pathlib import Path
from shutil import copyfile
from tempfile import NamedTemporaryFile

sourcefile = Path("/path/to/source").resolve()
insert_lineno = 152  # The line to insert the new data into.
insert_data = "..."  # Some string to insert.

with sourcefile.open(mode="r") as source:
    destination = NamedTemporaryFile(mode="w", dir=str(sourcefile.parent))
    lineno = 1

    while lineno < insert_lineno:
        destination.file.write(source.readline())
        lineno += 1

    # Insert the new data.
    destination.file.write(insert_data)

    # Write the rest in chunks.
    while True:
        data = source.read(1024)
        if not data:
            break
        destination.file.write(data)

# Finish writing data.
destination.flush()
# Overwrite the original file's contents with that of the temporary file.
# This uses a memory-optimised copy operation starting from Python 3.8.
copyfile(destination.name, str(sourcefile))
# Delete the temporary file.
destination.close()
Run Code Online (Sandbox Code Playgroud)

编辑 2020-09-08:我刚刚在 Code Review 上找到了一个答案,它做了与上面类似的事情,并提供了更多解释 - 它可能对某些人有用。


jor*_*anm 6

您只需将数据读入列表并将新记录插入所需的位置即可.

names = []
with open('names.txt', 'r+') as fd:
    for line in fd:
        names.append(line.split(' ')[-1].strip())

    names.insert(2, "Charlie") # element 2 will be 3. in your list
    fd.seek(0)
    fd.truncate()

    for i in xrange(len(names)):
        fd.write("%d. %s\n" %(i + 1, names[i]))
Run Code Online (Sandbox Code Playgroud)


red*_*rry 5

您没有向我们展示输出的外观,因此一种可能的解释是您希望将其作为输出:

  1. 阿尔弗雷德
  2. 法案
  3. 查理
  4. 唐纳德

(插入Charlie,然后在所有后续行中加1。)这是一种可能的解决方案:

def insert_line(input_stream, pos, new_name, output_stream):
  inserted = False
  for line in input_stream:
    number, name = parse_line(line)
    if number == pos:
      print >> output_stream, format_line(number, new_name)
      inserted = True
    print >> output_stream, format_line(number if not inserted else (number + 1), name)

def parse_line(line):
  number_str, name = line.strip().split()
  return (get_number(number_str), name)

def get_number(number_str):
  return int(number_str.split('.')[0])

def format_line(number, name):
  return add_dot(number) + ' ' + name

def add_dot(number):
  return str(number) + '.'

input_stream = open('input.txt', 'r')
output_stream = open('output.txt', 'w')

insert_line(input_stream, 3, 'Charlie', output_stream)

input_stream.close()
output_stream.close()
Run Code Online (Sandbox Code Playgroud)


Tem*_*olf 5

我发现有多种技术组合可以解决此问题:

with open(file, 'r+') as fd:
    contents = fd.readlines()
    contents.insert(index, new_string)  # new_string should end in a newline
    fd.seek(0)  # readlines consumes the iterator, so we need to start over
    fd.writelines(contents)  # No need to truncate as we are increasing filesize
Run Code Online (Sandbox Code Playgroud)

在我们的特定应用程序中,我们想在某个字符串后添加它:

with open(file, 'r+') as fd:
    contents = fd.readlines()
    if match_string in contents[-1]:  # Handle last line to prevent IndexError
        contents.append(insert_string)
    else:
        for index, line in enumerate(contents):
            if match_string in line and insert_string not in contents[index + 1]:
                contents.insert(index + 1, insert_string)
                break
    fd.seek(0)
    fd.writelines(contents)
Run Code Online (Sandbox Code Playgroud)

如果您希望它在匹配的每个实例之后插入字符串,而不是仅在第一个实例之后,则删除else:(并适当地缩进)和break

另请注意,and insert_string not in contents[index + 1]:防止它在之后添加多个副本match_string,因此可以安全地重复运行。