Reputation: 9492
I am trying to change a some lines in a text file without affecting the other lines. This is what's inside the text file called "text.txt"
this is a test1|number1
this is a test2|number2
this is a test3|number2
this is a test4|number3
this is a test5|number3
this is a test6|number4
this is a test7|number5
this is a test8|number5
this is a test9|number5
this is a test10|number5
My objective is to change the line 4 and line 5 but keep the rest same.
mylist1=[]
for lines in open('test','r'):
a=lines.split('|')
b=a[1].strip()
if b== 'number3':
mylist1.append('{}|{} \n'.format('this is replacement','number7'))
else:
mylist1.append('{}|{} \n'.format(a[0],a[1].strip()))
myfile=open('test','w')
myfile.writelines(mylist1)
Even though the code works, I am wondering if there is any better and efficient way to do it? Is it possible to read the file just by line number?
Upvotes: 1
Views: 31450
Reputation: 1421
It's not wholly clear whether your intent is to identify the lines to be replaced by their value, or by their line number.
If the former is your intent, you can get a list of lines like this:
with open('test','r') as f:
oldlines = f.read().splitlines()
If there's a danger of trailing whitespace, you could also:
Then you can process them like this:
newlines = [ line if not line.strip().endswith('|number3') else 'this is replacement|number7' for line in oldlines]
Open the destination file (I'm assuming you want to overwrite the original, here), and write all the lines:
with open('test','w') as f:
f.write("\n".join(newlines))
This is a general pattern that's useful for any kind of simple line-filtering.
If you meant to identify the lines by number, you could just alter the 'newlines' line:
newlines = [ line if i not in (3, 4) else 'this is replacement|number7' for i, line in enumerate(oldlines)]
Upvotes: 0
Reputation: 65791
There is not much you can improve. But you have to write all lines to a new file, either changed or unchanged. Minor improvements would be:
with
statement;lines
without formatting in the else
clause (if applicable).Applying all of the above:
import shutil
with open('test') as old, open('newtest', 'w') as new:
for line in old:
if line.rsplit('|', 1)[-1].strip() == 'number3':
new.write('this is replacement|number7\n')
else:
new.write(line)
shutil.move('newtest', 'test')
Upvotes: 11
Reputation: 4182
try this solution
with open('test', inplace=True) as text_file:
for line in text_file:
if line.rsplit('|', 1)[-1].strip() == 'number3':
print '{}|{} \n'.format('this is replacement', 'number7')
else:
print line
Upvotes: 0
Reputation: 133554
import fileinput
for lines in fileinput.input('test', inplace=True):
# inplace=True redirects stdout to a temp file which will
# be renamed to the original when we reach the end of the file. this
# is more efficient because it doesn't save the whole file into memeory
a = lines.split('|')
b = a[1].strip()
if b == 'number3':
print '{}|{} '.format('this is replacement', 'number7')
else:
print '{}|{} '.format(a[0], a[1].strip())
Upvotes: 3
Reputation: 798676
No. Files are byte-oriented, not line-oriented, and changing the length of a line will not advance the following bytes.
Upvotes: 2