I have a file with a lot of parameters for a software, it looks like that :
CMaterial::m_HurkxPrefactor=6.14
CMaterial::m_HurkxFgamma=368800
CRegion::m_FrontDiff1:
In CDiffusion: ver_num=1
CDiffusion::m_Enable=0
CDiffusion::m_Type=0
CDiffusion::m_Profile=2
CDiffusion::m_Npeak=1e+020
CDiffusion::m_Depth=1.5e-005
CDiffusion::m_Xpeak=0
CRegion::m_FrontDiff2:
In CDiffusion: ver_num=1
CDiffusion::m_Enable=0
CDiffusion::m_Type=1
CDiffusion::m_Profile=0
CDiffusion::m_Npeak=9e+016
CDiffusion::m_Depth=0.018
CDiffusion::m_Xpeak=0
(with much more rows)
There is several region, the first "CDiffusion::m_Enable" control the properties of the first region, and the second apparition is for setting the second region.
I wish to take this text file and replace with my values. For the moment I know how to change several parameter with this code, however it poorly manage the repetition of parameters in the file :
params = {'CDiffusion::m_Type': 3,
'CDiffusion::m_Depth' : 0.018
}
EDIT : missed this part of code
lab, val = [], []
for k, v in params.items():
lab.append(k)
value.append(v)
s = f.read()
for num, val in enumerate(lab):
s = re.sub('{0}=(.?)*'.format(val), '{1}={0}'.format(value[num], val), s)
but now I want for example to change "CDiffusion::m_Type" to 3 and the second "CDiffusion::m_Type" to 4.
Using this list of parameters and changing depending on the apparition of this last.
params = {'CDiffusion::m_Type': 3,
'CDiffusion::m_Type': 4,
}
Any help would be appreciated, thanks in advance!
EDIT2: @JoeIddon solution's is working, however i would like to maybe push it further:
lines = open('Test4.txt').read().strip().split('\n')
params = {
'CDiffusion::m_Type': ['3', 'False' ,'4'],
'CDiffusion::m_Depth': ['5', '6', '5']
}
with open('Test4.txt', 'w') as fh:
for l in lines:
try:
k, v = l.split('=')
if params[k] != 'False':
nl = k + '=' + params[k].pop(0)
else:
nl = l
params[k].pop(0)
except (KeyError, IndexError, ValueError):
nl = l
fh.write(nl + '\n')
print(nl)
fh.closed
I would like to not change the line if a certain value is in param, in this case 'false'. It doesn't seem to work though
Dictionary keys must be unique, so that last dictionary is invalid. What you really want is a dictionary where the values are lists. This will allow you to specify what the replacements should be in order. Also, as they are replacements in a file, they must be strings, not ints.
So, for example:
params = {
'CDiffusion::m_Type': ['3', '4'],
'CDiffusion::m_Depth': ['5', '6']
}
Now, to do this replacements in order, we cannot use .replace as that changes all occurrences; instead we must write our own method.
To do this, we could iterate over each line, split on the '=', and then retrieve the next replacement value from params. For that we can pop off the first item in the list (the first replacement) and use that when writing this new line (nl in the code).
The only last things we need to consider are the cases when the key (so the first half of the split) is not in our params dictionary and then also when it is in the dictionary, but for some reason, there is no replacement there to be made (i.e. the list is empty). These can be caught with KeyError and IndexErrors respectively (so we will need a try...except). In addition, upon testing, I realised that not all the lines actually have '='s, so we also need to catch ValueError, for this case.
update:
You were very close with trying to add a case where the value isn't changed, but you had two things wrong.
First, since Python lists are allowed different data types in them (strings, ints, more lists, etc.), it will probably be easier to just literally use False instead of 'False', which will make the check easier.
Secondly, when you check if this case is one where need to skip (False), you are checking params[k]. This is wrong since params[k] will give us the list of replacements, not the next replacement. For the next replacement, you need to pop(0) as we have been doing.
So, the code (with params already defined and the update):
lines = open('f.txt').read().strip().split('\n')
with open('f.txt', 'w') as fh:
for l in lines:
try:
k, v = l.split('=')
r = params[k].pop(0)
if r:
nl = k + '=' + r
else:
nl = l
except (KeyError, IndexError, ValueError):
nl = l
fh.write(nl + '\n')
Ok, I just tested it and it works; here's the file afterwards:
CMaterial::m_HurkxPrefactor=6.14
CMaterial::m_HurkxFgamma=368800
CRegion::m_FrontDiff1:
In CDiffusion: ver_num=1
CDiffusion::m_Enable=0
CDiffusion::m_Type=3
CDiffusion::m_Profile=2
CDiffusion::m_Npeak=1e+020
CDiffusion::m_Depth=5
CDiffusion::m_Xpeak=0
CRegion::m_FrontDiff2:
In CDiffusion: ver_num=1
CDiffusion::m_Enable=0
CDiffusion::m_Type=4
CDiffusion::m_Profile=0
CDiffusion::m_Npeak=9e+016
CDiffusion::m_Depth=6
CDiffusion::m_Xpeak=0
notice how the first CDiffusion::m_Type is now 3, and the second one 4, as well as how the first CDiffusion::m_Depth is now 5 and the second 6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With