I have a file with following format:
device={
id=1
tag=10
name=device1
}
device={
id=2
tag=20
name=device2
}
device={
id=3
tag=30
name=device3
}
So let's say I am only interested in device with id=2 and I want to extract its tag number(this is configurable and will be changed from some other code). So I need to extract tag number of the device id 2. How can I do this in python. I have done following:
ID='id=2'
with open("file.txt") as file:
for line in file:
if line.strip() == ID:
#Here I do not know what to write
# to extract 20
Thanks
With re.search function:
import re
with open('file.txt', 'r') as f:
id_num = 'id=2'
tag_num = re.search(r'' + id_num + '\s+tag=([0-9]+)', f.read())
print(tag_num.group(1))
The output:
20
f.read() - reads the file contents (as text)
r'' + id_num + '\s+tag=([0-9]+)' - constructing regex pattern, so it would become id=2\s+tag=([0-9]+) where \s is one or many whitespace characters(including newlines) and ([0-9]+) is the 1st captured group containing tag number
tag_num.group(1) - extracting the value of the 1st captured/parenthesized group 1 from the match object tag_num
You can read the next line using line.readline() try to use this code:
ID='id=2'
with open("file.txt") as file:
while True:
line = file.readline()
if line.strip() == ID:
nextline = file.readline()
result = nextline.strip().split('=')[1]
if line == '':
break
with open("") as file:
#print file.read()
for line in file:
#print line.split()
if line.strip()==ID:
d=file.next() #reads next line
print d.split('=')[1]
break
Related
I want to replace a whole line in a text document, if there is a line that begins with "truck_placement"
Can I remove the whole line when it contains "truck_placement" and then write the new text?
I tried it but it only inserts the new text und doesn't replace the whole line.
Thats the current code:
cordget = coordinatesentry.get()
fin = open(save_file,"r")
filedata = fin.read()
fin.close
newdata = filedata.replace("truck_placement: " , "truck_placement: " + cordget)
fin = open(save_file, "w")
fin.write(newdata)
fin.close
Your best bet is to append all the lines without "truck_placement" to a new file. This can be done with the following code:
original = open("truck.txt","r")
new = open("new_truck.txt","a")
for line in original:
if "truck_placement" not in line:
new.write(line)
original.close()
new.close()
You can either read the whole file into one string and replace the line using regular expression:
import re
cordget = "(value, one) (value, two)"
save_file = "sample.txt"
with open(save_file, "r") as f:
data = f.read()
# Catch the line from "truck_placement: " until the newline character ('\n')
# and replace it with the second argument, where '\1' the catched group
# "truck_placement: " is.
data = re.sub(r'(truck_placement: ).*\n', r'\1%s\n' % cordget, data)
with open(save_file, "w") as f:
f.writelines(data)
Or you could read the file as a list of all lines and overwrite the specific line:
cordget = "(value, one) (value, two)"
save_file = "sample.txt"
with open(save_file, "r") as f:
data = f.readlines()
for index, line in enumerate(data):
if "truck_placement" in line:
data[index] = f"truck_placement: {cordget}\n"
with open(save_file, "w") as f:
f.writelines(data)
I am having trouble with matching variables to lines in txt, and removing the lines.
I am currently doing a hotel room booking program in which I am having trouble removing a booking from my text file.
This is how my lines in my text file are formatted:
first_name1, phonenumber1 and email 1 are linked to entry boxes
jeff;jeff#gmail.com;123123123;2019-06-09;2019-06-10;Single Room
def edit_details(self,controller):
f = open("Bookings.txt")
lines = f.readlines()
f.close()
x = -1
for i in lines:
x += 1
data = lines[x]
first_name1 = str(controller.editName.get())
phonenumber1 = str(controller.editPhone.get())
email1 = str(controller.editEmail.get())
checkfirst_name, checkemail, checkphone_num, checkclock_in_date, checkclock_out_date, checkroom = map(str, data.split(";"))
if checkfirst_name.upper() == first_name1.upper() and checkemail.upper() == email1.upper() and checkphone_num == phonenumber1:
controller.roomName.set(checkfirst_name)
controller.roomEmail.set(checkemail)
controller.roomPhone.set(checkphone_num)
controller.roomCheckin.set(checkclock_in_date)
controller.roomCheckout.set(checkclock_out_date)
controller.roomSelect.set(checkroom)
print(controller.roomName.get())
print(controller.roomSelect.get())
controller.show_frame("cancelBooking")
break
elif x > len(lines) - int(2):
messagebox.showerror("Error", "Please Enter Valid Details")
break
I have the user to enter their details to give me the variables but I don't know how to match these variables to the line in the text file to remove the booking.
Do I have to format these variables to match the line?
This is what i have tried but it deletes the last line in my file
line_to_match = ';'.join([controller.roomName.get(),controller.roomEmail.get(),controller.roomPhone.get()])
print(line_to_match)
with open("Bookings.txt", "r+") as f:
line = f.readlines()
f.seek(0)
for i in line:
if i.startswith(line_to_match):
f.write(i)
f.truncate()
I have kind of added a pseudocode here. You can join the variables using ; and validate if the line startswith those details, like below.
first_name1, phonenumber1, email1 = 'jeff', 'jeff#gmail.com', '123123123'
line_to_match = ';'.join([first_name1, email1, phonenumber1])
for i in line:
...
if i.startswith(line_to_match):
# Add your removal code here
...
I can change the text in a file line by line, but I don't know how to write the results (changes) into the file.
This is a small part of my file:
<name>2016-09-15_obere-firstalm_gehen-6,5km</name>
<extensions>
<line xmlns="http://www.topografix.com/GPX/gpx_style/0/2">
<color>000000</color>
</line>
</extensions>
<trkseg>
<trkpt lat="47.671193" lon="11.886518">
<ele>1115.6</ele>
<time>2016-09-15T11:57:44Z</time>
</trkpt>
<trkpt lat="47.670686" lon="11.886412">
<ele>1117.6</ele>
<time>2016-09-15T11:58:14Z</time>
</trkpt>
<trkpt lat="47.670821" lon="11.886459">
<ele>1055.6</ele>
<time>2016-09-15T11:58:44Z</time>
</trkpt>
With a Python script I change values of elevations by adding 30.
Example:
Before change:
elevation (ele) 1115.6,
after change:
elevation (ele) 1145.6
#This little Python adds 30 to elevation:
import re
f1 = raw_input("name of your GPX file: ")
f1 = open(f1,'r+')
for line in f1:
res = re.search(r"<(ele)>(.+)</\1>",line)
if res:
number=float(res.group(2))
number_elev=number+30
number_elev=str(number_elev)
ress = re.sub(r"<(ele)>(.+)", r"\2",number_elev)
#print shows correct new values between <ele> and </ele>
print ress + "\n"
###but how to write into the gpx file these changes?
f1.close()
print "OK"
Expected: Write the file with the changed lines.
Actual: I don't know how to write a change by regexp into the file.
Thx in advance for your help.
You'll first need to read all the lines in your file and write each one to the file replacing the ones matching the regex search.
Also since one more <ele>..</ele> tag sequences can be on the same line, you'll need to find all occurrences of those in the line and replace them accordingly.
import re
f1 = raw_input("name of your GPX file: ")
with open(f1,'r') as f:
lines = f.readlines()
with open(f1, 'w') as f:
for line in lines:
ress = line
res = re.findall(r"<(ele)>(.+)</\1>",ress)
if res:
for r in res:
number=float(r[1])
number_elev=number+30
number_elev=str(number_elev)
ress=re.sub(r"<(ele)>{}</(ele)>".format(r[1]), r"<ele>{}</ele>".format(number_elev),string=ress, count=1)
f.write(ress)
Don't try to read and write from/to the same file at the same time. Just create and output file and write to it.
The following code is untested but it should work.
import re
f1 = input("name of your GPX file: ")
input_file = open(f1,'r+')
output_file = open(f1 + '_output', 'w+')
for line in input_file:
res = re.search(r"<(ele)>(.+)</\1>", line)
if res:
number=float(res.group(2))
number_elev=number+30
number_elev=str(number_elev)
line = line.replace(res.group(2), number_elev)
output_file.write(line)
input_file.close()
output_file.close()
print("OK")
You can read the file all at once and apply the regex to the data and write out the modified data to another file as follows:
import re
with open('input-file.xml') as fd:
data = fd.read()
regex = re.compile('(<ele>)([\d.]+)(</ele>)')
while True:
match = regex.search(data)
if not match:
break
new_value = float(match.group(2)) + 30
# <ele>6373.8</ele> becomes </ele>6373.8<ele> so that it doesnt match again
data = regex.sub(r'\g<3>{}\g<1>'.format(new_value), data, count=1)
# undo </ele>...<ele> the tag reversal done inside the while loop
regex = re.compile('(</ele>)([\d.]+)(<ele>)')
data = regex.sub(r'\3\2\1', data)
with open('output-file.xml', 'w') as fd:
fd.write(data)
Assume:
self.base_version = 1000
self.target_version = 2000
I have a file as follows:
some text...
<tsr_args> \"upgrade_test test_mode=upgrade base_sw=1000 target_sw=2000 system_profile=eth\"</tsr_args>
some text...
<tsr_args> \"upgrade_test test_mode=rollback base_sw=2000 target_sw=1000 system_profile=eth manufacture_type=no-manufacture\"</tsr_args>
some text...
<tsr_args> \"upgrade_test test_mode=downgrade base_sw=2000 target_sw=1000 system_profile=eth no_boot_next_enable_flag=True\"</tsr_args>
I need the base and target version values to be placed as specified above (Note that on the 2nd and 3rd entry, the base and target are opposite).
I tried to do it as follows, but it does not work:
base_regex = re.compile('.*test_mode.*base_sw=(.*)')
target_regex = re.compile('.*test_mode.*target_sw=(.*)')
o = open(file,'a')
for line in open(file):
if 'test_mode' in line:
if 'upgrade' in line:
new_line = (re.sub(base_regex, self.base_version, line))
new_line = (re.sub(target_regex, self.target_version, line))
o.write(new_line)
elif 'rollback' in line or 'downgrade' in line):
new_line = (re.sub(base_regex, self.target_version, line))
new_line = (re.sub(target_regex, self.base_version, line))
o.write(new_line)
o.close()
Assume the above code runs properly without any syntax errors.
The file is not modified at all.
The complete line is modified instead of just the captured group. How can I make re.sub to substitute only the captured group?
You are opening file with a -> append. So, your changes should be at the end of file. You should create a new file and replace old_one at the end of your script.
There is only one way I know if you want replace several matching groups: first of all you find word using regexp and replace it like a string without regexp.
Thanks Jimilan for your remarks. I fixed my code, and now it`s working:
base_regex = re.compile(.*test_mode.*base_sw=(\S*))
target_regex = re.compile(.*test_mode.*target_sw=(\S*))
for file in self.upgrade_cases_files_list:
file_handle = open(file, 'r')
file_string = file_handle.read()
file_handle.close()
base_version_result = base_regex.search(file_string)
target_version_result = target_regex.search(file_string)
if base_version_result is not None:
current_base_version = base_version_result.group(1)
else:
raise Exception("Could not detect base version in the following file: -> %s \n" % (file))
if target_version_result is not None:
current_target_version = target_version_result.group(1)
else:
raise Exception("Could not detect target version in the following file: -> %s \n" % (file))
file_string = file_string.replace(current_base_version, self.base_version)
file_string = file_string.replace(current_target_version, self.target_version)
file_handle = open(file, 'w')
file_handle.write(file_string)
file_handle.close()
I have the codez:
import re
pattern = ','
firstNames = "dictionary//first_names.txt"
new_file = []
def openTxtFile(txtFile):
file = open (txtFile,"r")
data = file.read()
print (data)
file.close
def parseTextFile(textFile):
openTxtFile(firstNames)
for line in lines:
match = re.search(pattern, line)
if match:
new_line = match.group() + '\n'
print (new_line)
new_file.append(new_line)
with open(firstNames, 'w') as f:
f.seek(0)
f.writelines(new_file)
I am trying to take the original file, match it on a "," and return line by line to a New file the string before the "," I'm having trouble putting all this together, thanks!
Use the csv module, since your original file is comma separated:
import csv
with open('input_file.txt') as f:
reader = csv.reader(f)
names = [line[0] for line in reader]
with open('new_file.txt','w') as f:
for name in names:
f.write('{0}\n'.format(name))