Writing onto file, If exact name is in line then... Else - python

Here is the part of my program which firstly reads a file, checking if the "name" which the user would give is in the file, if it is, then it would add onto the line, but if it isn't then it would start a new line.
r = open("Class%s.txt"%(group),"r")
lines = r.readlines()
r.close()
for i, line in enumerate(lines):
if name in line:
lines[i] = line.strip() + "\t" + str(score) + "\n"
break
else:
lines.append("\n" + name + "\t" + str(score))
w = open("Class%s.txt"%(group),"w")
w.writelines(lines)
w.close()
The problem I have with this program is that if a user named "Alexander" uses the program before a user named "Alex" does so, the program would write "Alex"'s score on the same line as "Alexander"'s as it searches each line for the characters "Alex" and not if it is the EXACT match. Thanks for any help given!

I presume each line looks like
Alexander 25 31 19 16
I suggest comparing like
if name.lower() == line.split(None, 1)[0].lower():
(compare against the line's first word, and ignore capitalization).

Just change
if name in line:
with
if name in line.strip():
This way you'll look into a list of words, not a list of characters. And you'll match complete words.

Related

Python script to remove certain things form a string

i have a file with many lines like this,
>6_KA-RFNB-1505/2021-EPI_ISL_8285588-2021-12-02
i need to convert it to
>6_KA_2021-1202
all of the lines that require this change start in a >
The 6_KA and the 2021-12-02 are different for all lines.
I also need to add an empty line before every line that i change in thsi manner.
UPDATE: You changed the requirements from when I originally answered yourpost, but the below does what you are looking for. The principle remains the same: use regex to identify the parts of the string you are looking to replace. And then as you are going thru each line of the file create a new string based on the values you parsed out from the regex
import re
regex = re.compile('>(?P<first>[0-9a-zA-Z]{1,3}_[0-9a-zA-Z]{1,3}).*(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})\n')
def convert_file(inputFile):
with open(inputFile, 'r') as input, open('Output.txt', 'w') as output:
for line in input:
text = regex.match(line)
if text:
output.write("\n" + text.group("first") + '_' + text.group("year") + "-" + text.group("month") + text.group("day") + "\n")
else:
output.write(line)
convert_file('data.txt')

Search lines, pull specific data

I need to read a text file, search all lines, find a keyword in a specific location of the line and if it exists, pull other data from that same line.
My example is the word 'TRED'. If TRED is at index location 95 I need to pull data from either certain columns or specific indexes from that line.
Currently my code is this....but it's not finding the word and so the results are all errors.
substr = "TRED"
with open(strFileLoc + "test.txt", 'r') as inputfile:
for line in inputfile:
if line.find(substr, 95, 98) != -1:
print(line.rstrip('\n'))
else:
print("There was an error at " + line.rstrip('\n'))
There are a couple of ways to solve the problem. The issue (based on my quick test) is caused by the substring call you make: str.find() indexes from the first position you give to the last-1, so the substring you're looking for in this case would be 3 characters long (TRE) even if there would be a match at that position. So you could fix it by simply increasing the end position to 99.
However, find() also returns the position where it finds a substring, (-1) if not found. You could achieve a good outcome by searching without specifying a location and checking the return value instead, thus robustly handling the case of a shorter string.
substr = "TRED"
with open(strFileLoc + "test.txt", 'r') as inputfile:
for line in inputfile:
loc = line.find(substr)
if loc == 95:
print(line.rstrip('\n'))
else:
print("There was an error at " + line.rstrip('\n'))
I believe there is an easier way to do this comparison. Check out the below code.
substr = "TRED"
with open(strFileLoc + "test.txt", 'r', 'r') as inputfile:
for line in inputfile:
if line[95:99] == substr:
print(line.rstrip('\n'))
else:
print("There was an error at " + line.rstrip('\n'))
Ouput:
sdaksdkakslkdlaksjdlkajslkdjlkajklsfjslkdvnksdjjlsjdlfjlskldfjlsnvkjdglsjdfljalsmnljklasjlfaaaaTREDdjsalkjdlka
Make sure you are giving the proper index values.(Note: line[95:99], will take elements at 95,96,97,98 position only).
You mentioned you'd want to pull from either columns or indices on that line.
If your file is space, comma, tab, etc. separated you can split each line into columns very easily. Hence, you can do this:
substr = "TRED"
token_splitter = ',' # or whatever separator you have
column_number = 2
with open(strFileLoc + "test.txt", 'r', 'r') as inputfile:
for line in inputfile:
columns = line.rstrip().split(token_splitter)
if columns[column_number] == substr: # get the exact column directly
print(line.rstrip('\n'))
else:
print("There was an error at " + line.rstrip('\n'))

Why does it write to 2 lines in a text file when I only ask it to type 1?

Basically I need to write a line to a txt file containing details about a product, these details are from another text file which I split. The final detail which is the quantity variable is an inputted number.
document = open('Task2.txt', 'r')
strquantity = str(quantity)
for line in document:
the_line = line.split(",")
if the_line[0] == GTIN:
with open("receipt.txt", "a") as receipt:
receipt.write(the_line[0] + "," + the_line[1]+ "," +the_line[2] + "," + strquantity)
document.close()
The task 2 file contains:
12345670,spatula,0.99
57954363,car,1000.20
09499997,towel,1.20
The quantity number is 5 and the GTIN number is 12345670. The line it should write to the file is:
12345670,spatula,0.99,5
But instead it writes:
12345670,spatula,0.99,
5
(no line space (five on the next line under))
Why does it do this and how do I make it so it just writes to the 1 line? Thanks.
The reason is because when you read in each line, it will have a newline at the end. So when you call split, the final entry will also contain a newline, so when you write the_list[2] it will split the line at this point. To get around this, call strip() to remove the newline as follows:
with open('Task2.txt', 'r') as document, open("receipt.txt", "a") as receipt:
strquantity = str(quantity)
for line in document:
the_line = line.strip().split(",")
if the_line[0] == GTIN:
receipt.write(','.join(the_line[0], the_line[1], the_line[2], strquantity) + '\n')
you need to trim the newline character from each line just before exploding it.
the_line=line.strip()
the_line=the_line.split(",")

Python 3; Writing to text files, unintentional newline (beginner)

The following function is a part of my future program, a library program. This particular function is supposed to fetch books from a text file, and if the user desires, "loan" them and thereby adding a string "(LOANED)" after the author of the book. The books are sorted by title first, followed by a comma and a space (, ) and then the author of the book. What I want to do is to just, simply, add a "(LOANED)" string after the author of the book in the text file. However, when I try this the (LOANED) string just ends up on a different line (one line below) from where I want it to be, and it's driving me nuts.
def lend_book(title):
f = open("booksbytitle.txt", "r+")
d={}
#splits the registry up into a dictionary with the book title as key and the book author as value to that key
for i in f:
x=i.split(",")
a=x[0]
b=x[1]
d[a]=b[0:(len(b))]
#checks if the title is in the dictionary, else skips down and quits the function
if title in d:
print("\n", title, "is available in the library and is written by"+d[title])
saved_author = d[title][1:]
while True:
alternative=input("Do you want to lend this book? [y/n] ")
if alternative.lower() == "y":
print("The book is now loaned ")
break
elif alternative.lower() == "n":
print("Okay, going back to main menu.. ")
break
else:
print("That is not a valid choice. Type 'y' or 'n'")
f.close()
loaned="(LOANED)"
f=open("booksbytitle.txt", "r+")
z=f.readlines()
f.seek(0)
for i in z:
if title not in i:
f.write(i)
f.write("\n" + title + ", " + saved_author + loaned)
f.truncate()
f.close()
#clears the program of unintented blank lines
fh = open("booksbytitle.txt", "r")
lines = fh.readlines()
fh.close()
keep = []
for line in lines:
if not line.isspace():
keep.append(line)
fh = open("booksbytitle.txt", "w")
fh.write("".join(keep))
fh.close()
else:
print("There wasnt a book by that name found in the registry")
It's hard to tell with the screwed-up formatting and the meaningless one-letter variable names, but I suspect the problem is this:
When you iterate the lines of a file, like for i in f:, each one ends with a newline character ('\n').
When you split(",") each one, the last split-off string still contains that newline.
So ultimately, when you try to stick that string in the middle of a string, it's got a newline at the end, which means you end up with a newline in the middle of the string.
To fix this, use rstrip on each line as you read them in:
for i in f:
x = i.rstrip().split(",")
This may mean that you're now missing newlines in your output to the file. You were expecting to get them for free, but now you don't. So you may have to do something like this:
f.write("\n" + title + ", " + saved_author + loaned + "\n")
However, maybe not. I notice that for some reason you're putting a "\n" at the start of every line, so this may just mean you end up with extra blank lines between each line (along with the extra blank line at the start of your file, which is inherent in using "\n" +).
You could use rstrip() on the strings to remove the right spaces (newlines),
and then join over "\n" instead of the empty string.
PS: You can write a bit of this code much simpler, by the way. For instance, you can just get the lines in the file all at once, filter out the empty ones and rstrip all at the same time, like this:
with open(filename, "r") as handler:
keep = [line.rstrip() for line in handler if line]
(The 'with' takes care of automatically closing the file after the indented block, then there's a list comprehension, and the open file object "handler" gives you the lines when iterating over it.)

Replace Line with New Line in Python

I am reading a text file and searching data line by line, based on some condition, changing some values in the line and writing it back into another file. The new file should not contain the old Line. I have tried the following, but it did not work. I think I am missing a very basic thing.
Solution: In C++ we can increment line but in Python I am not sure how to achieve this. So as of now, I am writing old line than new line. But in the new file, I want only the new line.
Example:
M0 38 A 19 40 DATA2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
M0 VBN A 19 40 TEMP2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
The code which i tried is the following:
def parsefile():
fp = open("File1", "rb+")
update_file = "File1" + "_update"
fp_latest = open(update_file, "wb+")
for line in fp:
if line.find("DATA1") == -1:
fp_latest.write(line)
if line.find("DATA1") != -1:
line = line.split()
pin_name = find_pin_order(line[1])
update_line = "DATA " + line[1] + " " + pin_name
fp_latest.write(update_line)
line = ''.join(line)
if line.find("DATA2") != -1:
line_data = line.split()
line_data[1] = "TEMP2"
line_data =' '.join(line_data)
fp_latest.write(line_data)
if line.find("DATA3") != -1:
line_data = line.split()
line_data[1] = "TEMP3"
line_data =' '.join(line_data)
fp_latest.write(line_data)
fp_latest.close()
fp.close()
The main problem with your current code is that your first if block, which checks for "DATA1" and writes the line out if it is not found runs when "DATA2" or "DATA3" is present. Since those have their own blocks, the line ends up being duplicated in two different forms.
Here's a minimal modification of your loop that should work:
for line in fp:
if line.find("DATA1") != -1:
data = line.split()
pin_name = find_pin_order(data[1])
line = "DATA " + data[1] + " " + pin_name
if line.find("DATA2") != -1:
data = line.split()
data[1] = "TEMP2"
line =' '.join(data)
if line.find("DATA3") != -1:
data = line.split()
data[1] = "TEMP3"
line =' '.join(data)
fp_latest.write(line)
This ensures that only one line is written because there's only a single write() call in the code. The special cases simply modify the line that is to be written. I'm not sure I understand the modifications you want to have done in those cases, so there may be more bugs there.
One thing that might help would be to make the second and third if statements into elif statements instead. This would ensure that only one of them would be run (though if you know your file will never have multiple DATA entries on a single line, this may not be necessary).
If you want to write a new line in a file replacing the old content that has been readed last time, you can use the file.seek() method for moving arround the file, there is an example.
with open("myFile.txt", "r+") as f:
offset = 0
lines = f.readlines()
for oldLine in lines:
... calculate the new line value ...
f.seek(offset)
f.write(newLine)
offset += len(newLine)
f.seek(offset)

Categories