Reputation: 245
I've been having a lot of trouble with programmatic find and replace, in Matlab. I have reproduced a MWE here.
Say I have the following code in a textfile called 'BaseJac3.txt':
x2 = -S1_2*(r1+a*K+a*P)+k*KS1_1+d*(PS1_1+KS1_2);
x3 = -S1_3*(r1+a*K+a*P)+k*KS1_2+d*(PS1_2+KS1_3);
x4 = -S1_4*(r1+a*K+a*P)+k*KS1_3+d*(PS1_3+KS1_4);
x5 = -S1_5*(r2+a*K+a*P)+k*KS1_4+d*(PS1_4+KS1_5);
I need to replace
S1_2
with y(2)
, ... , S1_5
with y(5)
;
KS1_1
through KS1_5
with y(52)
to y(57)
PS1_1
through PS1_4
with y(102)
to y(105)
How can I do this? I've tried using this: http://www.mathworks.com/matlabcentral/fileexchange/42877-find-and-replace-in-files
and also my following code:
text1 = fileread('BaseJac3.txt');
for k = 1:4
regexprep(text1,['PS1_' num2str(k)],['y(' num2str(k+101) ')']);
end
for k = 1:5
regexprep(text1,['KS1_' num2str(k)],['y(' num2str(k+51) ')']);
end
for k = 2:5
regexprep(text1,['S1_' num2str(k)],['y(' num2str(k) ')']);
end
but neither seems to be working properly. I'm not sure about regular expressions.
Thanks in advance for help.
Upvotes: 2
Views: 277
Reputation: 12214
Some regex whiz can probably work up a way to do this all in one shot, but for clarity I've split it into 3 passes. regexprep
works on cell arrays of strings so you can pass it the entire array at once.
function newstr = testcode(str)
helper = @(x,y) num2str(str2double(x) + y); % Generate anonymous function for our dynamic regexrep expression
pass1 = regexprep(str, '(?<!(K|P))S1_(\d*)', 'y($1)'); %S1
pass2 = regexprep(pass1, 'KS1_(\d*)', 'y(${helper($1,51)})'); % KS1
pass3 = regexprep(pass2, 'PS1_(\d*)', 'y(${helper($1,101)})'); % PS1
newstr = pass3;
end
What I've done here is utilize regexprep
's Tokens and Dynamic Expressions to format the output.
Pass 1 works on S1
, and uses a lookbehind assertion to ignore KS1
and PS1
. The expression matches the digit following S1_
and uses it as the token for y()
.
Passes 2 and 3 work on KS1
and PS1
. These use the same token approach for the match but also use a dynamic expression for the replacement. These allow us to pass a token to any MATLAB function that returns a string, and uses that string as the replacement. I've defined a helper anonymous function, helper
, to take care of the desired index offset.
With the following input:
str = {'x2 = -S1_2*(r1+a*K+a*P)+k*KS1_1+d*(PS1_1+KS1_2);'; ...
'x3 = -S1_3*(r1+a*K+a*P)+k*KS1_2+d*(PS1_2+KS1_3);'; ...
'x4 = -S1_4*(r1+a*K+a*P)+k*KS1_3+d*(PS1_3+KS1_4);'; ...
'x5 = -S1_5*(r2+a*K+a*P)+k*KS1_4+d*(PS1_4+KS1_5);' ...
};
We get the following output:
>> A = testcode(str)
A =
'x2 = -y(2)*(r1+a*K+a*P)+k*y(52)+d*(y(102)+y(53));'
'x3 = -y(3)*(r1+a*K+a*P)+k*y(53)+d*(y(103)+y(54));'
'x4 = -y(4)*(r1+a*K+a*P)+k*y(54)+d*(y(104)+y(55));'
'x5 = -y(5)*(r2+a*K+a*P)+k*y(55)+d*(y(105)+y(56));'
Upvotes: 2
Reputation: 5672
At the very least you need to save the output from the regexprep
command:
text1 = fileread('BaseJac3.txt');
for k = 1:4
text1 = regexprep(text1,['PS1_' num2str(k)],['y(' num2str(k+101) ')']);
end
for k = 1:5
text1 = regexprep(text1,['KS1_' num2str(k)],['y(' num2str(k+51) ')']);
end
for k = 2:5
text1 = regexprep(text1,['S1_' num2str(k)],['y(' num2str(k) ')']);
end
Upvotes: 0