ubaabd
ubaabd

Reputation: 435

Dynamic regexprep in MATLAB

I have the following strings in a long string:

a=b=c=d;
a=b;
a=b=c=d=e=f;

I want to first search for above mentioned pattern (X=Y=...=Z) and then output like the following for each of the above mentioned strings:

a=d;
b=d;
c=d;

a=b;

a=f;
b=f;
c=f;
d=f;
e=f;

In general, I want all the variables to have an equal sign with the last variable on the extreme right of the string. Is there a way I can do it using regexprep in MATLAB. I am able to do it for a fixed length string, but for variable length, I have no idea how to achieve this. Any help is appreciated.

My attempt for the case of two equal signs is as follows:

funstr = regexprep(funstr, '([^;])+\s*=\s*+(\w+)+\s*=\s*([^;])+;', '$1 = $3; \n $2 = $3;\n');

Upvotes: 2

Views: 335

Answers (3)

Hoki
Hoki

Reputation: 11792

Not a regexp but if you stick to Matlab you can make use of the cellfun function to avoid loop:

str = 'a=b=c=d=e=f;' ; %// input string

list = strsplit(str,'=') ;
strout = cellfun( @(a) [a,'=',list{end}] , list(1:end-1), 'uni', 0).' %'// Horchler simplification of the previous solution below 

%// this does the same than above but more convoluted
%// strout = cellfun( @(a,b) cat(2,a,'=',b) , list(1:end-1) , repmat(list(end),1,length(list)-1) , 'uni',0 ).'

Will give you:

strout = 
    'a=f;'
    'b=f;'
    'c=f;'
    'd=f;'
    'e=f;'

Note: As Horchler rightly pointed out in comment, although the cellfun instruction allows to compact your code, it is just a disguised loop. Moreover, since it runs on cell, it is notoriously slow. You won't see the difference on such simple inputs, but keep this use when super performances are not a major concern.


Now if you like regex you must like black magic code. If all your strings are in a cell array from the start, there is a way to (over)abuse of the cellfun capabilities to obscure your code do it all in one line.

Consider:

strlist = {
'a=b=c=d;'
'a=b;'
'a=b=c=d=e=f;'
};

Then you can have all your substring with:

strout = cellfun( @(s)cellfun(@(a,b)cat(2,a,'=',b),s(1:end-1),repmat(s(end),1,length(s)-1),'uni',0).' , cellfun(@(s) strsplit(s,'=') , strlist , 'uni',0 ) ,'uni',0)
>> strout{:}
ans = 
    'a=d;'
    'b=d;'
    'c=d;'
ans = 
    'a=b;'
ans = 
    'a=f;'
    'b=f;'
    'c=f;'
    'd=f;'
    'e=f;'

This gives you a 3x1 cell array. One cell for each group of substring. If you want to concatenate them all then simply: strall = cat(2,strout{:});

Upvotes: 2

hjpotter92
hjpotter92

Reputation: 80629

I haven't had much experience w/ Matlab; but your problem can be solved by a simple string split function.

[parts, m] = strsplit( funstr, {' ', '='}, 'CollapseDelimiters', true )

Now, store the last part of parts; and iterate over parts until that:

len = length( parts )
for i = 1:len-1
    print( strcat(parts(i), ' = ', parts(len)) )
end

I do not know what exactly is the print function in matlab. You can update that accordingly.

Upvotes: 1

Rodrigo López
Rodrigo López

Reputation: 4259

There isn't a single Regex that you can write that will cover all the cases. As posted on this answer:

https://stackoverflow.com/a/5019658/3393095

However, you have a few alternatives to achieve your final result:

  1. You can get all the values in the line with regexp, pick the last value, then use a for loop iterating throughout the other values to generate the output. The regex to get the values would be this:

    matchStr = regexp(str,'([^=;\s]*)','match')

  2. If you want to use regexprep at any means, you should write a pattern generator and a replace expression generator, based on number of '=' in the input string, and pass these as parameters of your regexprep func.

  3. You can forget about Regex and Split the input to generate the output looping throughout the values (similarly to alternative #1) .

Upvotes: 0

Related Questions