Anda dapat melakukannya seperti ini:
with open("/etc/apt/sources.list", "r") as sources:
lines = sources.readlines()
with open("/etc/apt/sources.list", "w") as sources:
for line in lines:
sources.write(re.sub(r'^# deb', 'deb', line))
Pernyataan with memastikan bahwa file ditutup dengan benar, dan membuka kembali file di "w"
mode mengosongkan file sebelum Anda menulisnya. re.sub(pattern, replace, string) setara dengan s/pattern/replace/ di sed/perl.
Edit: memperbaiki sintaks dalam contoh
Membuat sed
buatan sendiri penggantian dengan Python murni dengan no perintah eksternal atau ketergantungan tambahan adalah tugas mulia yang sarat dengan ranjau darat yang mulia. Siapa sangka?
Meskipun demikian, itu layak. Itu juga diinginkan. Kita semua pernah ke sana, orang-orang:"Saya perlu membuat beberapa file teks biasa, tetapi saya hanya memiliki Python, dua tali sepatu plastik, dan sekaleng ceri Maraschino kelas bunker yang berjamur. Tolong."
Dalam jawaban ini, kami menawarkan solusi terbaik yang menyatukan kehebatan jawaban sebelumnya tanpa semua yang tidak menyenangkan tidak -keangkeran. Sebagai catatan plundra, jawaban terbaik David Miller menulis file yang diinginkan secara non-atomik dan karenanya mengundang kondisi balapan (misalnya, dari utas dan/atau proses lain yang mencoba membaca file itu secara bersamaan). Itu buruk. Jawaban Plundra yang luar biasa memecahkan itu masalah sambil memperkenalkan lebih banyak lagi – termasuk banyak kesalahan penyandian fatal, kerentanan keamanan kritis (gagal mempertahankan izin dan metadata lain dari file asli), dan pengoptimalan prematur menggantikan ekspresi reguler dengan pengindeksan karakter tingkat rendah. Itu juga buruk.
Kedahsyatan, bersatu!
import re, shutil, tempfile
def sed_inplace(filename, pattern, repl):
'''
Perform the pure-Python equivalent of in-place `sed` substitution: e.g.,
`sed -i -e 's/'${pattern}'/'${repl}' "${filename}"`.
'''
# For efficiency, precompile the passed regular expression.
pattern_compiled = re.compile(pattern)
# For portability, NamedTemporaryFile() defaults to mode "w+b" (i.e., binary
# writing with updating). This is usually a good thing. In this case,
# however, binary writing imposes non-trivial encoding constraints trivially
# resolved by switching to text writing. Let's do that.
with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file:
with open(filename) as src_file:
for line in src_file:
tmp_file.write(pattern_compiled.sub(repl, line))
# Overwrite the original file with the munged temporary file in a
# manner preserving file attributes (e.g., permissions).
shutil.copystat(filename, tmp_file.name)
shutil.move(tmp_file.name, filename)
# Do it for Johnny.
sed_inplace('/etc/apt/sources.list', r'^\# deb', 'deb')
massedit.py (http://github.com/elmotec/massedit) melakukan scaffolding untuk Anda hanya menyisakan regex untuk menulis. Ini masih dalam versi beta tetapi kami mengharapkan masukan.
python -m massedit -e "re.sub(r'^# deb', 'deb', line)" /etc/apt/sources.list
akan menunjukkan perbedaan (sebelum/sesudah) dalam format diff.
Tambahkan opsi -w untuk menulis perubahan pada file asli:
python -m massedit -e "re.sub(r'^# deb', 'deb', line)" -w /etc/apt/sources.list
Atau, Anda sekarang dapat menggunakan api:
>>> import massedit
>>> filenames = ['/etc/apt/sources.list']
>>> massedit.edit_files(filenames, ["re.sub(r'^# deb', 'deb', line)"], dry_run=True)
Ini adalah pendekatan yang berbeda, saya tidak ingin mengedit jawaban saya yang lain. Bersarang with
karena saya tidak menggunakan 3.1 (Di mana with A() as a, B() as b:
berfungsi).
Mungkin sedikit berlebihan untuk mengubah sources.list, tapi saya ingin meletakkannya di sana untuk pencarian di masa mendatang.
#!/usr/bin/env python
from shutil import move
from tempfile import NamedTemporaryFile
with NamedTemporaryFile(delete=False) as tmp_sources:
with open("sources.list") as sources_file:
for line in sources_file:
if line.startswith("# deb"):
tmp_sources.write(line[2:])
else:
tmp_sources.write(line)
move(tmp_sources.name, sources_file.name)
Ini harus memastikan tidak ada kondisi balapan dari orang lain yang membaca file tersebut. Oh, dan saya lebih suka str.startswith(...) ketika Anda dapat melakukannya tanpa regexp.