How to read a specific number in a text file containing a mixture of strings and numbers?

1 回表示 (過去 30 日間)
Hi everybody,
I want to read only "a specific number" (Bolded below) in a text file, which i've got from a Website simultaneously and print that numbers in another file. The file is a mixture of strings and numbers and look like as follows:
Hamburg-Fuhlsbuettel, Germany (EDDH) 53-38N 010-00E 15M
Jan 06, 2020 - 02:50 PM EST / 2020.01.06 1950 UTC
Wind: from the S (190 degrees) at 10 MPH (9 KT):0
Visibility: greater than 7 mile(s):0
Sky conditions: partly cloudy
Temperature: 41 F (5 C)
Dew Point: 33 F (1 C)
Relative Humidity: 75%
Pressure (altimeter): 30.12 in. Hg (1020 hPa)
ob: EDDH 061950Z 19009KT 9999 SCT021 05/01 Q1020 NOSIG
cycle: 20
*****************************************************
I'd tried it with this matlab code:
request = webread('http://tgftp.nws.noaa.gov/data/observations/metar/decoded/EDDH.TXT'); %EDDH OIMM EGDX
fid=fopen('weather.txt','w');
fprintf(fid,'%s\n',request);
% a=string(request);
% a=split(request,'\n');
fclose(fid);
c=textread('weather.txt','%s','delimiter','\n')
Temp=extractBetween(c(6,:),"(","C");
LuftF=extractBetween(string(c(8,1)),': ','%');
LuftD=extractBetween(string(c(9,1)),'Hg (','hPa');
Tempe=str2double(Temp);
LuftFeu=str2double(LuftF);
LuftDru=str2double(LuftD);
% fW=fopen('T_P_H.txt','w+');
% fprintf(fW,'%s\n',request);
disp(' Tempe[°C] LuftDru[hPa] LuftFeu[%]');
M=[Tempe,LuftDru,LuftFeu]
but the Problem is here the number of Line for (Temperature,Humidity,Pressure) changed over the time. Could you please help me to solve the problem ? Many thanks in advance.
best Regards

採用された回答

per isakson
per isakson 2020 年 1 月 6 日
編集済み: per isakson 2020 年 1 月 7 日
Try this
%%
chr = webread('http://tgftp.nws.noaa.gov/data/observations/metar/decoded/EDDH.TXT');
%%
cac = regexp( chr, '^Temperature:[^(]+\((\d+)\x20+C\)\x20*$', 'tokens', 'lineanchors' );
T = str2double(cac{1}{1});
cac = regexp( chr, '^Relative Humidity:\x20+(\d+)%\x20*$', 'tokens', 'lineanchors' );
RH = str2double(cac{1}{1});
cac = regexp( chr, '^Pressure \(altimeter\):[^(]+\((\d+)\x20+hPa\)\x20*$', 'tokens', 'lineanchors' );
p = str2double(cac{1}{1});
%%
T, RH, p
it just returned
T =
4
RH =
80
p =
1019
Comments
  • Regular expressions are powerful and fast, but a bit tricky to use.
  • The function, extractBetween(), and a handful of others were recently added to Matlab because (I guess) regular expressions are tricky.
  • It's error prone to write regular expressions based a single example of the input. Small changes in the string format may break the code.
  • I often use \x20 for space because I find it robust.
  • Here (\d+) catches one or more digits, which doesn't allow for decimals. Replacing (\d+) by ([\d\.]+) catches numbers with decimals. (One backslash too many doesn't hurt, but one too few often does.)
  • And a leading plus or minus, I was about to forget them. Thus, I have to add [+-]? and ends up with ([+-]?[\d\.]+).
  • This code assumes that the sub-strings of interest appears only once in the text. Adding 'once' to the regexp() call catches the first occurence and avoids searching the rest of the text.
Modified code
%%
tic
cac = regexp( chr, '^Temperature:[^(]+\(([+-]?[\d\.]+)\x20+C\)\x20*$'...
, 'tokens', 'lineanchors', 'once' );
T = str2double(cac{1});
cac = regexp( chr, '^Relative Humidity:\x20+([+-]?[\d\.]+)%\x20*$' ...
, 'tokens', 'lineanchors', 'once' );
RH = str2double(cac{1});
cac = regexp( chr, '^Pressure \(altimeter\):[^(]+\(([+-]?[\d\.]+)\x20+hPa\)\x20*$' ...
, 'tokens', 'lineanchors', 'once' );
p = str2double(cac{1});
toc
.
And a code based on extractBetween()
%%
rows = strsplit( chr, '\n' );
tic
% Search the row numbers of the rows of interest
ixS = find( startsWith( ...
rows, {'Temperature:','Relative Humidity:','Pressure (altimeter):'} ) );
%
Temp = extractBetween( rows(ixS(1)), "(" , "C" );
LuftF = extractBetween( rows(ixS(2)), ': ' , '%' );
LuftD = extractBetween( rows(ixS(3)), 'Hg (', 'hPa' );
Tempe=str2double(Temp);
LuftFeu=str2double(LuftF);
LuftDru=str2double(LuftD);
toc
.
The regexp code is somewhat faster and the extractBetween code is much more readable. However, the regexp code is most likely much faster (than the extractBetween code) with the rows of interest in the beginning of a huge text.
  1 件のコメント
MoHa
MoHa 2020 年 1 月 7 日
per isakson - the code works perfectly. I appreciate your kind assistance.

サインインしてコメントする。

その他の回答 (1 件)

Stephen23
Stephen23 2020 年 1 月 7 日
編集済み: Stephen23 2020 年 1 月 7 日
The regular expression doesn't need to be so complex:
>> chr = webread('http://tgftp.nws.noaa.gov/data/observations/metar/decoded/EDDH.TXT');
>> opt = {'tokens','dotexceptnewline','ignorecase'};
>> rgx = '(Temperature|Relative Humidity|Pressure).+\W(\d+\.?\d*)\s*(C|%|hPa)';
>> tkn = regexp(chr,rgx,opt{:});
>> tkn = vertcat(tkn{:})
tkn =
'Temperature' '5' 'C'
'Relative Humidity' '75' '%'
'Pressure' '1020' 'hPa'
>> vec = str2double(tkn(:,2))
vec =
5
75
1020
  3 件のコメント
Stephen23
Stephen23 2020 年 1 月 7 日
"Thanks for your great code"
I hope it helped! Voting for my answer is an easy way to show your thanks.
per isakson
per isakson 2020 年 1 月 7 日
編集済み: per isakson 2020 年 1 月 7 日
Complex/tricky is in the eye of the beholder.
This code will make one search of the entire text compared to three and is faster than my "Modified code" (on my system). However, it returns negative temperatures as positive (same mistake as I initially did).

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeData Import and Export についてさらに検索

製品

Community Treasure Hunt

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

Start Hunting!

Translated by