回答:
まず、ファイルを開いて、ファイルからすべての行を取得します。次に、ファイルを書き込みモードで再度開き、削除する行を除いて、行を書き戻します。
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 +")で開き、シークを使用してfポインターをリセットしてから、最後の書き込み後にすべてを削除するために切り捨てます。
for
ループでエラーが発生した場合、ファイルが部分的に上書きされ、重複した行または行が半分切り取られてしまいます。代わりにf.truncate()
直後にしたい場合がありf.seek(0)
ます。そうすれば、エラーが発生した場合、ファイルが不完全になります。しかし、実際の解決策(ディスク容量がある場合)は、一時ファイルに出力し、すべてを成功させた後で、それを使用するos.replace()
かpathlib.Path(temp_filename).replace(original_filename)
、元のファイルと交換することです。
i.strip('\n') != "line you want to remove..."
受け入れられた回答に記載されているように追加してもらえれば、それで私の問題は完全に解決されます。理由だけでi
私のために何もしませんでした
すべてをリストに保存し、ファイルを再度開いて書き込むのではなく、最良かつ最速のオプションは、ファイルを別の場所に書き直すことです。
with open("yourfile.txt", "r") as input:
with open("newfile.txt", "w") as output:
for line in input:
if line.strip("\n") != "nickname_to_delete":
output.write(line)
それでおしまい!1つのループと1つだけで同じことができます。それははるかに速くなります。
(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
現在の行に文字列が存在しないかどうかを評価するためのより明確なこの回答で説明されているfileinputアプローチが好きでした: テキストファイルからの行の削除(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でした
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
ファイルをリストに読み込んだ場合は、リストを反復処理して、削除したいニックネームを探すことができると思います。追加のファイルを作成しなくても、非常に効率的に行うことができますが、結果をソースファイルに書き戻す必要があります。
これが私がこれを行う方法です:
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未満のもの)には過剰です。
おそらく、あなたはすでに正しい答えを得ていますが、これは私のものです。フィルター処理されていないデータを収集するためにリストを使用する代わりに(readlines()
方法は何をするか)、2つのファイルを使用します。1つはメインデータを保持するためのもので、もう1つは特定の文字列を削除するときにデータをフィルター処理するためのものです。ここにコードがあります:
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()
これがお役に立てば幸いです。:)
ファイル行をリストに保存してから、削除する行をリストから削除し、残りの行を新しいファイルに書き込みます
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)
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)
ファイルの特定の行を行番号で削除するには:
変数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コードの方がわかりやすいかもしれません。
fileinput
@ JF-セバスチャンによって記載されているように、ここで。簡単なfor
構文で、一時ファイルを介して1行ずつ作業できるようです。