【发布时间】:2011-06-10 06:02:30
【问题描述】:
假设我有一个包含昵称的文本文件。如何使用 Python 从此文件中删除特定昵称?
【问题讨论】:
-
尝试
fileinput,如@j-f-sebastian here 所述。它似乎允许您通过一个临时文件逐行工作,所有这些都使用简单的for语法。
假设我有一个包含昵称的文本文件。如何使用 Python 从此文件中删除特定昵称?
【问题讨论】:
fileinput,如@j-f-sebastian here 所述。它似乎允许您通过一个临时文件逐行工作,所有这些都使用简单的for 语法。
首先,打开文件并从文件中获取所有行。然后以写入模式重新打开文件并写回您的行,除了您要删除的行:
with open("yourfile.txt", "r") as f:
lines = f.readlines()
with open("yourfile.txt", "w") as f:
for line in lines:
if line.strip("\n") != "nickname_to_delete":
f.write(line)
您需要在比较中使用strip("\n") 换行符,因为如果您的文件不以换行符结尾,那么最后一个line 也不会。
【讨论】:
解决这个问题只需要一次打开:
with open("target.txt", "r+") as f:
d = f.readlines()
f.seek(0)
for i in d:
if i != "line you want to remove...":
f.write(i)
f.truncate()
此解决方案以 r/w 模式(“r+”)打开文件,并利用 seek 重置 f 指针,然后在最后一次写入后截断以删除所有内容。
【讨论】:
for 循环中遇到错误,您将得到一个部分覆盖的文件,其中包含重复的行或半截断行。您可能想在f.seek(0) 之后直接使用f.truncate()。这样,如果您遇到错误,您最终会得到一个不完整的文件。但真正的解决方案(如果你有磁盘空间)是输出到一个临时文件,然后在一切成功后使用os.replace() 或pathlib.Path(temp_filename).replace(original_filename) 将其与原始文件交换。
i.strip('\n') != "line you want to remove...",这将完美地解决我的问题。因为只是i 并没有为我做任何事情
我认为最好和最快的选择是在其他地方重新写入文件,而不是将所有内容存储在列表中并重新打开文件进行写入。
with open("yourfile.txt", "r") as file_input:
with open("newfile.txt", "w") as output:
for line in file_input:
if line.strip("\n") != "nickname_to_delete":
output.write(line)
就是这样!在一个循环中,只有一个循环,你可以做同样的事情。它会快得多。
【讨论】:
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace(python v 3.3 中的新功能)比对mv 的系统调用更具跨平台性。
这是 @Lother 答案的“分叉”(我认为这应该被视为正确答案)。
对于这样的文件:
$ cat file.txt
1: october rust
2: november rain
3: december snow
来自 Lother 解决方案的这个分支工作正常:
#!/usr/bin/python3.4
with open("file.txt","r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if "snow" not in line:
f.write(line)
f.truncate()
改进:
with open,丢弃f.close()的用法
if/else 用于评估当前行中是否不存在字符串【讨论】:
在第一遍中读取行并在第二遍中进行更改(删除特定行)的问题是,如果文件很大,您将用完 RAM。相反,更好的方法是逐行读取行,然后将它们写入单独的文件,从而消除不需要的行。我已经使用 12-50 GB 的文件运行这种方法,并且 RAM 使用率几乎保持不变。只有 CPU 周期显示正在进行处理。
【讨论】:
我喜欢这个答案中解释的 fileinput 方法: Deleting a line from a text file (python)
例如,我有一个文件,其中包含空行,我想删除空行,这是我解决它的方法:
import fileinput
import sys
for line_number, line in enumerate(fileinput.input('file1.txt', inplace=1)):
if len(line) > 1:
sys.stdout.write(line)
注意:在我的例子中,空行的长度为 1
【讨论】:
您可能已经得到了正确答案,但这是我的答案。
我没有使用列表来收集未过滤的数据(readlines() 方法所做的),而是使用两个文件。一个是保留主要数据,第二个是在删除特定字符串时过滤数据。这是一个代码:
main_file = open('data_base.txt').read() # your main dataBase file
filter_file = open('filter_base.txt', 'w')
filter_file.write(main_file)
filter_file.close()
main_file = open('data_base.txt', 'w')
for line in open('filter_base'):
if 'your data to delete' not in line: # remove a specific string
main_file.write(line) # put all strings back to your db except deleted
else: pass
main_file.close()
希望你会发现这很有用! :)
【讨论】:
如果您使用 Linux,可以尝试以下方法。
假设你有一个名为animal.txt 的文本文件:
$ cat animal.txt
dog
pig
cat
monkey
elephant
删除第一行:
>>> import subprocess
>>> subprocess.call(['sed','-i','/.*dog.*/d','animal.txt'])
然后
$ cat animal.txt
pig
cat
monkey
elephant
【讨论】:
-i 选项是非标准的,在 *BSD 平台(包括 macOS)上的工作方式与在 Linux 上的工作方式不同。 Python 的 fileinput 模块以透明、可移植和本机方式执行相同的操作。
我认为,如果您将文件读入列表,那么您可以遍历列表以查找要删除的昵称。您可以在不创建额外文件的情况下更高效地完成此操作,但您必须将结果写回源文件。
我可以这样做:
import, os, csv # and other imports you need
nicknames_to_delete = ['Nick', 'Stephen', 'Mark']
我假设 nicknames.csv 包含如下数据:
Nick
Maria
James
Chris
Mario
Stephen
Isabella
Ahmed
Julia
Mark
...
然后将文件加载到列表中:
nicknames = None
with open("nicknames.csv") as sourceFile:
nicknames = sourceFile.read().splitlines()
接下来,遍历列表以匹配要删除的输入:
for nick in nicknames_to_delete:
try:
if nick in nicknames:
nicknames.pop(nicknames.index(nick))
else:
print(nick + " is not found in the file")
except ValueError:
pass
最后,将结果写回文件:
with open("nicknames.csv", "a") as nicknamesFile:
nicknamesFile.seek(0)
nicknamesFile.truncate()
nicknamesWriter = csv.writer(nicknamesFile)
for name in nicknames:
nicknamesWriter.writeRow([str(name)])
nicknamesFile.close()
【讨论】:
一般来说,你不能;您必须重新编写整个文件(至少从更改点到结束)。
在某些特定情况下,您可以做得比这更好-
如果您的所有数据元素长度相同且没有特定顺序,并且您知道要删除的数据元素的偏移量,则可以将最后一项复制到要删除的数据上并截断之前的文件最后一项;
或者您可以使用“这是错误数据,跳过它”值覆盖数据块,或在您保存的数据元素中保留“此项目已被删除”标志,这样您就可以将其标记为已删除,而无需以其他方式修改文件。
这对于短文档(任何小于 100 KB 的文件?)来说可能是多余的。
【讨论】:
我喜欢这种使用 fileinput 和 'inplace' 方法的方法:
import fileinput
for line in fileinput.input(fname, inplace =1):
line = line.strip()
if not 'UnwantedWord' in line:
print(line)
它比其他答案少了一点罗嗦,并且足够快
【讨论】:
将文件行保存在列表中,然后从列表中删除要删除的行并将剩余行写入新文件
with open("file_name.txt", "r") as f:
lines = f.readlines()
lines.remove("Line you want to delete\n")
with open("new_file.txt", "w") as new_f:
for line in lines:
new_f.write(line)
【讨论】:
这是从文件中删除/某些行的其他方法:
src_file = zzzz.txt
f = open(src_file, "r")
contents = f.readlines()
f.close()
contents.pop(idx) # remove the line item from list, by line number, starts from 0
f = open(src_file, "w")
contents = "".join(contents)
f.write(contents)
f.close()
【讨论】:
您可以使用
re库
假设您能够加载完整的 txt 文件。然后定义一个不需要的昵称列表,然后用空字符串“”替换它们。
# Delete unwanted characters
import re
# Read, then decode for py2 compat.
path_to_file = 'data/nicknames.txt'
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
# Define unwanted nicknames and substitute them
unwanted_nickname_list = ['SourDough']
text = re.sub("|".join(unwanted_nickname_list), "", text)
【讨论】:
你想从文件中删除特定的行,所以使用这个 sn-p 简短的代码,你可以轻松地删除任何带有句子或前缀(符号)的行。
with open("file_name.txt", "r") as f:
lines = f.readlines()
with open("new_file.txt", "w") as new_f:
for line in lines:
if not line.startswith("write any sentence or symbol to remove line"):
new_f.write(line)
【讨论】:
通过行号删除文件的特定行:
将变量 filename 和 line_to_delete 替换为您的文件名和您要删除的行号。
filename = 'foo.txt'
line_to_delete = 3
initial_line = 1
file_lines = {}
with open(filename) as f:
content = f.readlines()
for line in content:
file_lines[initial_line] = line.strip()
initial_line += 1
f = open(filename, "w")
for line_number, line_content in file_lines.items():
if line_number != line_to_delete:
f.write('{}\n'.format(line_content))
f.close()
print('Deleted line: {}'.format(line_to_delete))
示例输出:
Deleted line: 3
【讨论】:
for nb, line in enumerate(f.readlines())
获取文件的内容,用换行符将其拆分为一个元组。然后,访问您的元组的行号,加入您的结果元组,并覆盖文件。
【讨论】:
tuple(f.read().split('\n'))?? (2)“访问你的元组的行号”和“加入你的结果元组”听起来很神秘;实际的 Python 代码可能更容易理解。