I poked at it a lot, and borrowed martineau's ideas, and ended up with this:
def change_file(filepath, add_comment, trigger_words):
def process(line):
line_word = line.lstrip(';').split(':')[0]
if line_word in trigger_words:
if add_comment:
line = line if line.startswith(';') else ';' + line
else:
line = line.lstrip(';')
return line
with open(filepath) as f:
content = [process(line) for line in f]
with open(filepath, 'r+') as f:
f.truncate()
f.write(''.join(content))
change_file('abc.txt', add_comment=True, trigger_words=["sys", "netdev"])
The main "nice" bit (that I like) is using a list comprehension [process(line) for line in f]
, because it does away with the whole final = ''; final += blah
arrangement. It processes every line and that's the output.
I've changed the flag
so instead of reading "flag is 0 or 1" (what does that mean?) it now reads "add_comment is True or False", to more clearly indicate what it does.
In terms of efficiency, it could be better; (make "trigger_words" a set so that testing membership was faster, change the way it normalizes every line for testing); but if you're processing a small file it won't make much difference Python is fast enough, and if you're processing an enormous file, it's more likely IO limited than CPU limited.
Try it online here: https://repl.it/CbTo/0 (it reads, and prints the results, it doesn't try to save).
(NB. .lstrip(';')
will remove all semicolons at the start of the line, not just one. I'm assuming there's only one).
Edit from the comments. Here's a version which will process the SQL Server UTF-16 install file without screwing it up, however I don't know of a general fix for this that will work for all files. Note this reads the file as a specific data encoding, and writes a binary file with a specific data encoding. And changes the split to =
for the SQL ini format. And doesn't truncate
because w
mode does that.
import codecs
def change_file(filepath, add_comment, trigger_words):
def process(line):
line_word = line.lstrip(';').split('=')[0]
if line_word in trigger_words:
if add_comment:
line = line if line.startswith(';') else ';' + line
else:
line = line.lstrip(';')
return line
with codecs.open(filepath, encoding='utf-16') as f:
content = [process(line) for line in f]
with codecs.open(filepath, 'wb', encoding='utf-16') as f:
f.write(''.join(content))
change_file('d:/t/ConfigurationFile - Copy.ini', add_comment=True, trigger_words=["ACTION", "ENU"])