Borrar filtros
Borrar filtros

Read single "cell" containing partly text and numbers

1 visualización (últimos 30 días)
Lars
Lars el 14 de Mayo de 2014
Respondida: dpb el 15 de Mayo de 2014
Hallo Matlab forum.
I have a problem with reading a single cell in a space separated text file. The cell is containing a letter and therefore dlmread isn't working.
Example of the file reading.
Kanal 1
Range 32768 N/Min/Max/Mean/Zero 3225000 88 288 184 0
Pressure sensor 1 (1)
X-POS/Y-POS/CAL/DIM 0 0 4.9681*x + -0.30715
Kanal 2
Range 32768 N/Min/Max/Mean/Zero 3225000 -553 -273 -378 0
Pressure sensor 2 (2)
X-POS/Y-POS/CAL/DIM 0 0 4.9811*x + 0.56611
I would like to end up with the value "4.9681" and "-0.30715".
Any suggestions on how to make it possible to read these values?

Respuesta aceptada

dpb
dpb el 14 de Mayo de 2014
Editada: dpb el 15 de Mayo de 2014
The brute-force way...
>> fmt='%*s %*f %*f %f*x + %f';
>> fid=fopen('lars.txt','r');
>> cell2mat(textscan(fid,fmt,'headerlines',3,'collectoutput',true))
ans =
4.9811 0.5661
Place in a loop either counted or
while ~feof(fid)
...
and concatenate results. If file is large so dynamic reallocation begins to hurt, preallocate a large array first and test for overflow...

Más respuestas (2)

Lars
Lars el 15 de Mayo de 2014
Hey dpb.
Thanks for a great answer it worked! I extended it to repeat for a lot more readings.
fid=fopen('Data.gtx','r');
for i=1:14,fgetl(fid);end % skip three records
l=fgetl(fid); % read one of interest
coeff=sscanf(l,'%*s%*d%*d %f*x +%f').'
for ii = 1:38
for i=1:3,fgetl(fid);end % rinse and repeat...
l=fgetl(fid);
coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x + %f').'
end
However i have discovered that some of readings i am tring to get are differing from the example above.
Kanal 7
Range 32768 N/Min/Max/Mean/Zero 3225000 851 4282 1190 0
Pressure sensor 7 (7)
X-POS/Y-POS/CAL/DIM 0 0 5.0082*x -2.05+0.55+1+1.35
Kanal 8
Range 32768 N/Min/Max/Mean/Zero 3225000 -10 3755 349 0
Pressure sensor 8 (8)
X-POS/Y-POS/CAL/DIM 0 0 4.924*x + 0.40764-0.1
Kanal 15
Range 32768 N/Min/Max/Mean/Zero 3225000 3349 22900 11397 0
Gauge array (1 from breakwater) (15)
X-POS/Y-POS/CAL/DIM 0 0 0.0023233*x^2 + 0.036253*x +0.19344
I tried with if sentences to define if the output:
for ii = 1:38
for i=1:3,fgetl(fid);end % rinse and repeat...
l=fgetl(fid);
coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x + %f').' ;
if coeff(ii+1,1) == coeff(ii+1,2); coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x - %f').' ; end
if coeff(ii+1,1) == coeff(ii+1,2); coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x + %f + %f').' ; end
if coeff(ii+1,1) == coeff(ii+1,2); coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x - %f + %f').' ; end
if coeff(ii+1,1) == coeff(ii+1,2); coeff(ii+1,:)=sscanf(l,'%*s%*d%*d %f*x^2 + %f*x + %f').' ; end
if coeff(ii+1,1) == coeff(ii+1,2); error('something is wrong'); end
end
But i had a hard time guessing all the possible combinations of the ifsentences i had to make. Are there a smarter way to read the numbers?

dpb
dpb el 15 de Mayo de 2014
Yeeeech! That's one of the worst formatting of output to parse I've ever seen. Who dreamed that up and why????
X-POS/Y-POS/CAL/DIM 0 0 5.0082*x -2.05+0.55+1+1.35
I think you'll have to back off and read the last field as character string instead of trying to parse it. I'll presume the former for the moment--
>> ll=' X-POS/Y-POS/CAL/DIM 0 0 5.0082*x -2.05+0.55+1+1.35'; % the trouble line
>> fmt1='%*s %*f %*f %f*x %s'; % format to get first value/last string
>> c=textscan(ll,fmt1)
c =
[5.0082] {1x1 cell}
>> eval(char(c{2}))
ans =
0.8500
>> c{2}
ans =
'-2.05+0.55+1+1.35'
>>
Ewwww...I just realized the last case is a quadratic -- now the number of strings is different as well. Looks like you'll have to read the whole line and then select the characters from 33:end and got thru then and find the number of terms by looking for operators +/- separated by blanks and then process each. I'm sure there's a way regexp could help but I'm not very adept at all with it. I use a little utility routine I've built to find and return an array of tokens for such cases--
>> ll
ll =
X-POS/Y-POS/CAL/DIM 0 0 5.0082*x -2.05+0.55+1+1.35
>> ll(33:end)
ans =
5.0082*x -2.05+0.55+1+1.35
>> t=tokens(ll(33:end))
t =
5.0082*x
-2.05+0.55+1+1.35
>> for i=1:size(t,1),eval(t(i,:)),end
ans =
5.0082
ans =
0.8500
>>
The one really bad case is the very first you showed that has the '+' sign between terms and then a negative value. That doesn't seem to show up later on, however, every time. It causes the following to happen--
>> l=' X-POS/Y-POS/CAL/DIM 0 0 4.9681*x + -0.30715';
>> tokens(l(33:end))
ans =
4.9681*x
+
-0.30715
>>
Namely the '+' shows up as an extra token so the processing loop would have to test for that case and skip it.
All this is doable, but certainly the creator did you no favors...
Here's my utility routine tokens, feel free to use it w/ attribution--
function tok = tokens(s,d)
% Simple string parser returns tokens in input string s
%
% STRTOK(S) the tokens in the string S delimited
% by "white space". Any leading white space characters are ignored.
%
% STRTOK(S,D) returns tokens delimited by one of the
% characters in D. Any leading delimiter characters are ignored.
% Get initial token and set up for rest
if nargin==1
[tok,r] = strtok(s);
while ~isempty(r)
[t,r] = strtok(r);
tok = strvcat(tok,t);
end
else
[tok,r] = strtok(s,d);
while ~isempty(r)
[t,r] = strtok(r,d);
tok = strvcat(tok,t);
end
end

Categorías

Más información sobre String Parsing en Help Center y File Exchange.

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by