How to read text data for a given pattern?

Greetings!
I have a text file with the following format.
r e s u l t a n t s a n d s t r e s s e s f o r t i m e s t e p 1 ( at time 0.00000E+00 )
element # =1 part ID = # material type= #
resultants axial shear-s shear-t moment-s moment-t torsion pl eps
0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00
integration point
sigma 11 sigma 12 sigma 31 plastic eps
1 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
2 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
3 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
4 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
element # =2 part ID = # material type= #
resultants axial shear-s shear-t moment-s moment-t torsion pl eps
0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00
integration point
sigma 11 sigma 12 sigma 31 plastic eps
1 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
2 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
3 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
4 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
element # =3 part ID = # material type= #
resultants axial shear-s shear-t moment-s moment-t torsion pl eps
0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00
integration point
sigma 11 sigma 12 sigma 31 plastic eps
1 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
2 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
3 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
4 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
element # =4 part ID = # material type= #
resultants axial shear-s shear-t moment-s moment-t torsion pl eps
0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00
integration point
sigma 11 sigma 12 sigma 31 plastic eps
1 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
2 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
3 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
4 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
The whole data repeats 500 times giving different values at respective times for all 4 element data.
I am trying to create a script that can extract the time (value after "at time"), element number (i.e. 1,2,3,4), and the axial, shear-s and shear-t for all the 500 iterations. Everything else is ignored.
Using 'for' loop, I was able to extract time values, but I am stuggling with extracting the axial, shear-s, and shear-t since my loop is for 500 but these values are present after every iteration for 4 elements, giving a total of 2000 values.
How can I script this to extract the values in an array?
Thanking in advance,
Warm regards.

 Accepted Answer

dpb
dpb on 22 Dec 2022
Edited: dpb on 23 Dec 2022
Always much better if you'll attach a section of the file for folks to work with...but try something like
file=readlines('yourfile.txt'); % read the file as string array
tlines=file(contains(file,'at time')); % extract the time step lines
t=str2double(extractBetween(tlines,'time',')')); % convert to time array
ix=find(contains(file,'resultants')); % find the stresses header lines
s=str2double(split(strip(file(ix+1)))); % convert to stresses array (one past header)
t=repmat(t,1,size(s,1)/numel(t)).'; % repeat t by number elements per time step
% following doesn't work -- see addendum/erratum below for fix...
tS=table(t(:),s,'VariableNames',{'Time',file(ix(1))}); % convert to table, make t column
Warning -- air code!! Salt to suit and beware of typos like mismatched parens, etc., ...
ADDENDUM: Patched and tested w/ sample file --dpb
ERRATUM: Excepting I didn't test the conversion to table all the way through -- the variable names won't work that way; it's not an array of strings but just one string -- sorry about that. The following code snippet will extract the names by finding where the end of each number is and backing up to the preceding...if the field width can be changed, this should deal with it...
s1=file(ix(1)+1); % save the stresses line as pattern to work from
iv2=find(s1{:}=='E')+3; % the end of each number field from the E+NN exponent
FL=diff(iv2); % the field width --
FL=[FL(1) FL] % presume first is same...
% split the first "resultants" record at the above points for table variable names
t1=strip(file(ix(1))); % the leading space is a problem because
t1=t1+blanks(strlength(s1)-strlength(t1)); % but have to have a line as long as numbers
vnames=strip(arrayfun(@(i1,i2)extractBetween(t1,i1,i2),iv2-FL+1,iv2,'uni',1));
array2table([t(:),s],'VariableNames',["Time" vnames]);
The file format is messed up -- unless was somehow corrupted in the posting...there's an offset of an extra column of the header for the two "moment-x" variables -- they go one character past the end of the numeric field column -- but, if add four instead of three to the index, then the line isn't long enough that way, either.
So, the above moves that line to parse left by one character by removing the leading blank and then padding it back onto the end...klunky, but needed to read the headers from the file instead of setting manually.
One could find the end of the column headings except they did you the favor of using an embedded blank in the last column so that's a hard one to deal with, too...

5 Comments

Hi. Thanks for the answer. Sorry for not attaching the text file. I have added it now. Coming to the issue. I am able to extract the values when we have just 1 iteration for given time. But what if we have 500 of these? After reading the text file using 'fopen' I had tried out the following loop previously. And it is able to return the values but not for all the iterations. What should I do to correctly fetch the values?
for b = 1:500
Line_1 = fgetl(elout);
time_data = strsplit(Line_1,' '); % Using 'space' as the delimiter
L = length(time_data); % Length of the line after split
time(b) = str2double(time_data{L-1}); % Time value extracted from the line
fgetl(elout);
fgetl(elout);
for i = 1:4
Line_2 = fgetl(elout);
delim = strfind(Line_2,'=');
beamID(i) = str2double(Line_2(delim(1)+1:delim(1)+8));
fgetl(elout);
fgetl(elout);
Line_3 = fgetl(elout);
forces_ID = strsplit(Line_3,' ');
F = length(forces_ID);
axial(i) = str2double(forces_ID{F-6});
shear_s(i) = str2double(forces_ID{F-5});
shear_t(i) = str2double(forces_ID{F-4});
for c = 1:10
fgetl(elout);
end
end
end
The code I posted should work as is, barring typos. Did you try it?
Yes, I did try the code. For conversion to stress array line, the variable 's' gives a matrix of NaN. Also, I am getting the following error.
Error using table
All table variables must have the same number of rows.
Error in Test (line 11)
tS=table(t,s,'VariableNames',{'Time',file(ix(1))});
Said was air code and "salt to suit..." :)
Forgot that str2double is fairly feeble and about the multiple elements per time step when putting the two together...but easy enough to fix.
s=str2double(split(strip(file(ix+1)))); % cuz strdouble needs non-whitespace delimiter
then to put the two together need to get a time value for each group -- also easy enough...
t=repmat(t,1,size(s,1)/numel(t)).'; % repeat t by number elements per time step
t=t(:); % and turn into column vector for table
I've patched the code in the answer...
Hey @dpb. The code works fine now. Thanks a lot for your assistance.

Sign in to comment.

More Answers (1)

You'll need to write a custom reader for that specialized format.
If you have any more questions, then attach your text file with the paperclip icon after you read this:

1 Comment

Hi. Sorry for the inconvenience. I have attached the text file now. Thanks for the answer.

Sign in to comment.

Categories

Products

Release

R2022a

Asked:

on 22 Dec 2022

Commented:

on 26 Dec 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!