Python File String Replace Dict and Tuple - python

have a Dict with multiple values in a tuple.
newhost = {'newhost.com': ('1.oldhost.com',
'2.oldhost.com',
'3.oldhost.com',
'4.oldhost.com')
}
I wanna open a existing file and search for lines in this file that contains a value of the oldhosts. A file can have multiple Account Lines. In example
Account: 1.oldhost.com username
Account: someotherhost username
When the line with 1.oldhost.com or 2.oldhost.com or 3.oldhost.com and so on is found i wanna replace it with the key form the dict newhost.com.
Can anyone help me? Searched alot, but didnt find the right thing.
Regards

Maybe something like this could get you started
infile_name = 'some_file.txt'
# Open and read the incoming file
with open(infile_name, 'r') as infile:
text = infile.read()
# Cycle through the dictionary
for newhost, oldhost_list in host_dict.items():
# Cycle through each possible old host
for oldhost in oldhost_list:
text.replace(oldhost, newhost)
outfile_name = 'some_other_file.txt'
# Write to file
with open(outfile_name, 'w') as outfile:
outfile.write(text)
Not claiming this to be the best solution, but it should be a good start for you.

To easily find the new host for a given old host, you should convert your data structure:
# your current structure
new_hosts = {
'newhost-E.com': (
'1.oldhost-E.com',
'2.oldhost-E.com',
),
'newhost-A.com': (
'1.oldhost-A.com',
'2.oldhost-A.com',
'3.oldhost-A.com',
),
}
# my proposal
new_hosts_2 = {
v: k
for k, v_list in new_hosts.items()
for v in v_list}
print(new_hosts_2)
# {
# '1.oldhost-E.com': 'newhost-E.com',
# '2.oldhost-E.com': 'newhost-E.com',
# '1.oldhost-A.com': 'newhost-A.com',
# '2.oldhost-A.com': 'newhost-A.com',
# '3.oldhost-A.com': 'newhost-A.com',
# }
This does repeat the new host names (the values in new_hosts_2), but it will allow you to quickly look up given an old host name:
some_old_host = 'x.oldhost.com'
the corresponding_new_host = new_hosts_2[some_old_host]
Now you just need to:
read the lines of the file
find the old hostname in that line
lookup the corresponding new host in new_hosts_2
replace that value in the line
write the line to a new file
Maybe like this:
with open(file_name_1, 'r') as fr:
with open(file_name_2, 'w') as fw:
for line in fr:
line = line.strip()
if len(line) > 0:
# logic to find the start and end position of the old host
start_i = ?
end_i = ?
# get and replace, but only if its found in 'new_hosts_2'
old_host = line[start_i:end_i]
if old_host in new_hosts_2:
line = line[:start_i] + new_hosts_2[old_host] + line[end_i:]
fw.write(line + '\n')

Thank you for your tips. I came up with this now and it is working fine.
import fileinput
textfile = 'somefile.txt'
curhost = 'newhost.com'
hostlist = {curhost: ('1.oldhost.com',
'2.oldhost.com',
'3.oldhost.com')
}
new_hosts_2 = {
v: k
for k, v_list in hostlist.items()
for v in v_list}
for line in fileinput.input(textfile, inplace=True):
line = line.rstrip()
if not line:
continue
for f_key, f_value in new_hosts_2.items():
if f_key in line:
line = line.replace(f_key, f_value)
print line

Related

Write parsed fasta file back to fasta format from a dictionary

I have created a function that parses a Fasta file because I needed to remove some odd characters. Now I have a dictionary and want to turn it back to a fasta format. I am new to Fasta files so I don't know how to proceed.
The dictionary has this format:
{'NavAb:/1126': 'TNIVESSFFTKFIIYLIVLNGITMGLETSKTFMQSFGVYTTLFNQIVITIFTIEIILRIYVHRISFFKDPWSLFDFFVVAISLVPTSSGFEILRVLRVLRLFRLVTAVPQMRKI', 'Shaker:/1656': 'SSQAARVVAIISVFVILLSIVIFCLETLEDEVPDITDPFFLIETLCIIWFTFELTVRFLACPLNFCRDVMNVIDIIAIIPYFITTLNLLRVIRLVRVFRIFKLSRHSKGLQIL', .....
The function:
def parse_file(input_file):
parsed_seqs = {}
curr_seq_id = None
curr_seq = []
for line in newfile:
line = line.strip()
line = line.replace('-', '')
if line.startswith(">"):
if curr_seq_id is not None:
parsed_seqs[curr_seq_id] = ''.join(curr_seq)
curr_seq_id = line[1:]
curr_seq = []
continue
curr_seq.append(line)
parsed_seqs[curr_seq_id] = ''.join(curr_seq)
return parsed_seqs
newfile = open("file")
parsed_seqs = parse_file(newfile)
print(parsed_seqs)
If you can use an existing library for this task, you may use Biotite:
import biotite.sequence.io.fasta as fasta
seq_dict = {
'NavAb:/1126': 'TNIVESSFFTKFIIYLIVLNGITMGLETSKTFMQSFGVYTTLFNQIVITIFTIEIILRIYVHRISFFKDPWSLFDFFVVAISLVPTSSGFEILRVLRVLRLFRLVTAVPQMRKI',
'Shaker:/1656': 'SSQAARVVAIISVFVILLSIVIFCLETLEDEVPDITDPFFLIETLCIIWFTFELTVRFLACPLNFCRDVMNVIDIIAIIPYFITTLNLLRVIRLVRVFRIFKLSRHSKGLQIL'
}
fasta_file = fasta.FastaFile()
for header, seq_str in seq_dict.items():
fasta_file[header] = seq_str
fasta_file.write("path/to/file.fasta")
path/to/file.fasta:
>NavAb:/1126
TNIVESSFFTKFIIYLIVLNGITMGLETSKTFMQSFGVYTTLFNQIVITIFTIEIILRIYVHRISFFKDPWSLFDFFVVA
ISLVPTSSGFEILRVLRVLRLFRLVTAVPQMRKI
>Shaker:/1656
SSQAARVVAIISVFVILLSIVIFCLETLEDEVPDITDPFFLIETLCIIWFTFELTVRFLACPLNFCRDVMNVIDIIAIIP
YFITTLNLLRVIRLVRVFRIFKLSRHSKGLQIL
Note that I belong to the developers of this package. There are also solutions in a multitude of other packages, such as Biopython.

Writing variables from GUI to text file in tkinter

I'm trying to write the text fields values to a file like this (where inputtxt is a Text widget):
input_file_name = inputtxt1.get('1.0', 'end-1c').replace(" ","")
num_of_compare_points = inputtxt2.get('1.0','end-1c')
VER = inputtxt3.get('1.0','end-1c')
mode = inputtxt4.get(1.0','end-1c')
executionMode = inputtxt5.get('1.0','end-1c')
numOfWorkers = inputtxt6.get ('1.0','end-1c')
sessionFile = inputtxt7.get('1.0','end-1c')
file = open("file_1.setup","w")
file.write (input_file_name + "\n" + num_of_compare_points + "\n" + Option+"\n"+VER+"\n"+mode+"\n"+executionMode+"\n"+numOfWorkers+"\n"+sessionFile)
This method was good but I want to write the variable name +the value to the file so that the user can fill the values from the file not only through GUI and the order in file will be irrelevant since we're storing in the variable itself , Example:
File_1.setup:
input_file_name = (some name the user can change it from here not from GUI)
num_of_compare_points = (some number the user can change it from here not from GUI)
.
.
.
etc
UPDATE: I'm using the file attribute:value in a restore finction which put the value of each attribute on its related text field ; the problem here that I have only the value but not the variable:value and the variables must be in order (I need the order to be irrelevent since I'll use the variable name)
def restore_info():
if os.stat('file_1.setup').st_size == 0:
print("Writing to setup file..")
else:
with open('file_1.setup','r') as f:
lines = list(line for line in (l.strip() for l in f) if line)
x = len(lines)
print (x)
for i in lines:
print (i)
if (x==7):
inputtxt1.insert('end',lines[0])
inputtxt2.insert('end',lines[1])
inputtxt3.insert['end',lines[2])
... etc
UPDATE2 : I've managed to split each line based on ":" but I need a way to tell the program where is variable and where is value
def restore_info():
if os.stat('file_1.setup').st_size == 0:
print("Writing to setup file..")
else:
with open('file_1.setup','r') as f:
lines = list(line for line in (l.strip() for l in f) if line)
x = len(lines)
print (x)
for i in lines:
splitted_i=i.split(":")
print (splitted_i)
UPDATE 3:Advantage of this step
User will be able to apply the value manually, and not only through GUI.
The order will be irrelevant.
Any amount of spaces should be allowed around and in between the variable name and its value.
It will be very easy to search file_1.setup and extract the value for each field.
What you need to do is to collect the data into a dict and dump it as key value pair
sessionFile = 'x'
executionMode = 'y'
data = {'sessionFile': sessionFile, 'executionMode': executionMode}
with open('out.txt', 'w') as f:
for k, v in data.items():
f.write(f'{k}:{v}\n')
out.txt
sessionFile:x
executionMode:y

How to insert a file with a list into a script?

I am trying to add a list file to a script.
I need to make it so that to take the public key data from the "list.txt" file and save all the results to the "save.txt" file?
from bitcoinlib.keys import Address
master = Address ("0341b40ab5b2972161f2ff3d5487e0fb8260f2d98221cc2eb4fa3f28b6ad10d81e", encoding = 'bech32', script_type = 'p2wpkh')
print (master.address)
At the moment I am getting one value
bc1q7wdz5dcs553f2y6qgf38xdgqs2kqgkhn5ydn9l
How to fix that in place of this value: 0341b40ab5b2972161f2ff3d5487e0fb8260f2d98221cc2eb4fa3f28b6ad10d81e
There was a list of this file "list.txt"
02485a4e62913be3db116d1ab15f84110599ea8905cd7dbae7be6fa02033fdb54e
0315da5f8f47787f6e8294bd369a4dd81aea97429630ecae831a9f6362a6917106
023741e71ebddc5eca046c9b23ac7c5230160fe1335e655c9bbe0b8a20c8d89802
037782a3fcc6c0ca092658a513c9f051cc95d540d215f0c965176c664d49d3e732
029c6c7748107fc9584a838df6a2c8224ae2339e2a95b15b4cd8bcc67c2d149cd5
To get all the value and save to the file "save.txt"
bc1q6jxrahx3rw6lt2nlv5fpsdtllyzaa03m4d98xv
bc1qct3fu8543tryapkq4kpgw5ph8cj74zhtrdp5sx
bc1q5a3h25vu4kn90sc70rkm65narezzw97khu4dhu
bc1qutzkrtc7tqqjgrzns3s3h92f8wfxvfhp99ppnn
bc1ql2slqxzp7c9hdxhlp0ehlzdg2qa94xh5lk2anw
Please help me with fixing the code!
As far as i'm concerned you want to use each line of file separately.
First read all the lines to list:
with open('list.txt', 'r') as f:
lists = [i.replace('\n', '') for i in f.readlines()]
Then for each line, create Address instance, and save it to another list:
addresses = []
for l in lists:
master = Address(l, encoding = 'bech32', script_type = 'p2wpkh')
addresses.append(master.address)
The last part is to save all to file save.txt
with open('save.txt', 'w+') as f:
for a in addresses:
f.write(a + '\n')

How do I search a file for a string and replace it with multiple lines in Python?

I am running Python 3.5.1
I have a text file that I'm trying to search through and replace or overwrite text if it matches a predefined variable. Below is a simple example:
test2.txt
A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE #
############################
More stuff here
Outdated line of information that has no comment above - message_label
The last line in this example needs to be overwritten so the new file looks like below:
test2.txt after script
A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE #
############################
More stuff here
# This is an important line that needs to be copied
Very Important Line of information that the above line is a comment for - message_label
The function I have written idealAppend does not work as intended and subsequent executions create a bit of a mess. My workaround has been to separate the two lines into single line variables but this doesn't scale well. I want to use this function throughout my script with the ability to handle any number of lines. (if that makes sense)
Script
#!/usr/bin/env python3
import sys, fileinput, os
def main():
file = 'test2.txt'
fullData = r'''
# This is an important line that needs to be copied
Very Important Line of information that the above line is a comment for - message_label
'''
idealAppend(file, fullData)
def idealAppend(filename, data):
label = data.split()[-1] # Grab last word of the Append String
for line in fileinput.input(filename, inplace=1, backup='.bak'):
if line.strip().endswith(label) and line != data: # If a line 2 exists that matches the last word (label)
line = data # Overwrite with new line, comment, new line, and append data.
sys.stdout.write(line) # Write changes to current line
with open(filename, 'r+') as file: # Open File with rw permissions
line_found = any(data in line for line in file) # Search if Append exists in file
if not line_found: # If data does NOT exist
file.seek(0, os.SEEK_END) # Goes to last line of the file
file.write(data) # Write data to the end of the file
if __name__ == "__main__": main()
Workaround Script
This seems to work perfectly as long as I only need to write exactly two lines. I'd love this to be more dynamic when it comes to number of lines so I can reuse the function easily.
#!/usr/bin/env python3
import sys, fileinput, os
def main():
file = 'test2.txt'
comment = r'# This is an important line that needs to be copied'
append = r'Very Important Line of information that the above line is a comment for - message_label'
appendFile(file, comment, append)
def appendFile(filename, comment, append):
label = append.split()[-1] # Grab last word of the Append String
for line in fileinput.input(filename, inplace=1, backup='.bak'):
if line.strip().endswith(label) and line != append: # If a line 2 exists that matches the last word (label)
line = '\n' + comment + '\n' + append # Overwrite with new line, comment, new line, and append data.
sys.stdout.write(line) # Write changes to current line
with open(filename, 'r+') as file: # Open File with rw permissions
line_found = any(append in line for line in file) # Search if Append exists in file
if not line_found: # If data does NOT exist
file.seek(0, os.SEEK_END) # Goes to last line of the file
file.write('\n' + comment + '\n' + append) # Write data to the end of the file
if __name__ == "__main__": main()
I am very new to Python so I'm hoping there is a simple solution that I overlooked. I thought it might make sense to try and split the fullData variable at the new line characters into a list or tuple, filter the label from the last item in the list, then output all entries but this is starting to move beyond what I've learned so far.
If I understand your issue correctly, you can just open the input and output files, then check whether the line contains old information and ends with the label and write the appropriate content accordingly.
with open('in.txt') as f, open('out.txt', 'r') as output:
for line in f:
if line.endswith(label) and not line.startswith(new_info):
output.write(replacement_text)
else:
output.write(line)
If you want to update the original file instead of creating a second one, it's easiest to just delete the original and rename the new one instead of trying to modify it in place.
Is this what you are looking for ? It's looking for a label and then replaces the whole line with whatever you want.
test2.txt
A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE #
############################
More stuff here
Here is to be replaced - to_replace
script.py
#!/usr/bin/env python3
def main():
file = 'test2.txt'
label_to_modify = "to_replace"
replace_with = "# Blabla\nMultiline\nHello"
"""
# Raw string stored in a file
file_replace_with = 'replace_with.txt'
with open(file_replace_with, 'r') as f:
replace_with = f.read()
"""
appendFile(file, label_to_modify, replace_with)
def appendFile(filename, label_to_modify, replace_with):
new_file = []
with open(filename, 'r') as f:
for line in f:
if len(line.split()) > 0 and line.split()[-1] == label_to_modify:
new_file.append(replace_with)
else:
new_file.append(line)
with open(filename + ".bak", 'w') as f:
f.write(''.join(new_file))
if __name__ == "__main__": main()
test2.txt.bak
A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE #
############################
More stuff here
# Blabla
Multiline
Hello
Reading over both answers I've come up with the following as the best solution i can get to work. It seems to do everything I need. Thanks Everyone.
#!/usr/bin/env python3
def main():
testConfFile = 'test2.txt' # /etc/apache2/apache2.conf
testConfLabel = 'timed_combined'
testConfData = r'''###This is an important line that needs to be copied - ##-#-####
Very Important Line of information that the above line is a \"r\" comment for - message_label'''
testFormatAppend(testConfFile, testConfData, testConfLabel) # Add new test format
def testFormatAppend(filename, data, label):
dataSplit = data.splitlines()
fileDataStr = ''
with open(filename, 'r') as file:
fileData = stringToDictByLine(file)
for key, val in fileData.items():
for row in dataSplit:
if val.strip().endswith(row.strip().split()[-1]):
fileData[key] = ''
fileLen = len(fileData)
if fileData[fileLen] == '':
fileLen += 1
fileData[fileLen] = data
else:
fileLen += 1
fileData[fileLen] = '\n' + data
for key, val in fileData.items():
fileDataStr += val
with open(filename, 'w') as file:
file.writelines(str(fileDataStr))
def stringToDictByLine(data):
fileData = {}
i = 1
for line in data:
fileData[i] = line
i += 1
return fileData
if __name__ == "__main__": main()

How to get only the values from the file while parsing it?

I am parsing a config file I would like to get only the values which are file paths in the file
for example the config file has
apache.access = /var/log/apache2/access.log
apache.errors = /var/log/apache2/errors.log
I would like to get only '/var/log/apache2/access.log' and '/var/log/apache2/errors.log' from the
COMMENT_CHAR = '#'
OPTION_CHAR = '='
def parse_config(filename):
options = {}
f = open(filename)
for line in f:
if COMMENT_CHAR in line:
line, comment = line.split(COMMENT_CHAR, 1)
if OPTION_CHAR in line:
option, value = line.split(OPTION_CHAR, 1)
option = option.strip()
value = value.strip()
options[option] = value
f.close()
return options
I tried this but it gives all the options and values in the file
apache.access : /var/log/apache2/access.log
apache.errors : /var/log/apache2/errors.log
First you have to define, what is a file path (1. does it have to exist? 2. does it have to be creatable in an existing directory? 3. anything else?). This tests whether the given string is a path pointing to an existing dir/file:
import os
# ...
[v for v in options.itervalues() if os.path.exists(v)]
Regular expressions is what you need. Here is little example how it could look
import re
f = open("apache.log")
for line in f:
m = re.match("apache\.(access|errors)\s+=\s+(.+)", line)
if None != m:
print (m.group(2))
f.close()

Categories

Resources