Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

remove first char from each line in a text file

im new to Python, to programming in general.

I want to remove first char from each line in a text file and write the changes back to the file. For example i have file with 36 lines, and the first char in each line contains a symbol or a number, and i want it to be removed.

I made a little code here, but it doesn't work as expected, it only duplicates whole liens. Any help would be appreciated in advance!

from sys import argv

run, filename = argv

f = open(filename, 'a+')
f.seek(0)
lines = f.readlines()
for line in lines:
    f.write(line[1:])
f.close()
like image 221
izdi Avatar asked Dec 05 '22 09:12

izdi


2 Answers

Your code already does remove the first character. I saved exactly your code as both dupy.py and dupy.txt, then ran python dupy.py dupy.txt, and the result is:

from sys import argv

run, filename = argv

f = open(filename, 'a+')
f.seek(0)
lines = f.readlines()
for line in lines:
    f.write(line[1:])
f.close()
rom sys import argv
un, filename = argv
 = open(filename, 'a+')
.seek(0)
ines = f.readlines()
or line in lines:
   f.write(line[1:])
.close()

It's not copying entire lines; it's copying lines with their first character stripped.


But from the initial statement of your problem, it sounds like you want to overwrite the lines, not append new copies. To do that, don't use append mode. Read the file, then write it:

from sys import argv

run, filename = argv

f = open(filename)
lines = f.readlines()
f.close()
f = open(filename, 'w')
for line in lines:
    f.write(line[1:])
f.close()

Or, alternatively, write a new file, then move it on top of the original when you're done:

import os
from sys import argv

run, filename = argv

fin = open(filename)
fout = open(filename + '.tmp', 'w')
lines = f.readlines()
for line in lines:
    fout.write(line[1:])
fout.close()
fin.close()
os.rename(filename + '.tmp', filename)

(Note that this version will not work as-is on Windows, but it's simpler than the actual cross-platform version; if you need Windows, I can explain how to do this.)


You can make the code a lot simpler, more robust, and more efficient by using with statements, looping directly over the file instead of calling readlines, and using tempfile:

import tempfile
from sys import argv

run, filename = argv

with open(filename) as fin, tempfile.NamedTemporaryFile(delete=False) as fout:
    for line in fin:
        fout.write(line[1:])
    os.rename(fout.name, filename)

On most platforms, this guarantees an "atomic write"—when your script finishes, or even if someone pulls the plug in the middle of it running, the file will end up either replaced by the new version, or untouched; there's no way it can end up half-way overwritten into unrecoverable garbage.

Again this version won't work on Windows. Without a whole lot of work, there is no way to implement this "write-temp-and-rename" algorithm on Windows. But you can come close with only a bit of extra work:

with open(filename) as fin, tempfile.NamedTemporaryFile(delete=False) as fout:
    for line in fin:
        fout.write(line[1:])
    outname = fout.name
os.remove(filename)
os.rename(outname, filename)

This does prevent you from half-overwriting the file, but it leaves a hole where you may have deleted the original file, and left the new file in a temporary location that you'll have to search for. You can make this a little nicer by putting the file somewhere easier to find (see the NamedTemporaryFile docs to see how). Or renaming the original file to a temporary name, then writing to the original filename, then deleting the original file. Or various other possibilities. But to actually get the same behavior as on other platforms is very difficult.

like image 110
abarnert Avatar answered Dec 06 '22 22:12

abarnert


You can either read all lines in memory then recreate file,

from sys import argv

run, filename = argv

with open(filename, 'r') as f:
    data = [i[1:] for i in f
with open(filename, 'w') as f:
    f.writelines(i+'\n' for i in data) # this is for linux. for win use \r\n

or You can create other file and move data from first file to second line by line. Then You can rename it If You'd like

from sys import argv

run, filename = argv

new_name = filename + '.tmp'
with open(filename, 'r') as f_in, open(new_name, 'w') as f_out:
    for line in f_in:
        f_out.write(line[1:])

os.rename(new_name, filename)
like image 39
oleg Avatar answered Dec 06 '22 21:12

oleg