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.

 채택된 답변

dpb
dpb 2022년 12월 22일
편집: dpb 2022년 12월 23일

0 개 추천

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

MatLim
MatLim 2022년 12월 23일
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
dpb
dpb 2022년 12월 23일
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...
MatLim
MatLim 2022년 12월 26일
Hey @dpb. The code works fine now. Thanks a lot for your assistance.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Image Analyst
Image Analyst 2022년 12월 22일

0 개 추천

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

MatLim
MatLim 2022년 12월 23일
Hi. Sorry for the inconvenience. I have attached the text file now. Thanks for the answer.

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Image Processing Toolbox에 대해 자세히 알아보기

제품

릴리스

R2022a

태그

질문:

2022년 12월 22일

댓글:

2022년 12월 26일

Community Treasure Hunt

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

Start Hunting!

Translated by