如何读取以随机行间隔放置字符串的数字数据?



我有一个数据文件,由空格分隔的数字行(四列)组成,每隔一段时间就会有一些文本。 下面是一个示例数据文件。我想提取有四列数字的部分。

如何跳过文本并仅阅读数字? 我尝试使用文本扫描:

filename = 'data.dat';
inputfile = fopen(filename);
delimiter = sprintf(' '); 
numberdata = textscan(inputfile, '%f%f%f%f','delimiter', delimiter);
fclose(inputfile);

我以为textscan会忽略所有不符合指定格式的数据,但事实并非如此。 它只是返回空数组。

总是有regexp,它愉快地忽略不匹配的文本。

标准十进制格式

考虑一个字符数组,由换行符分隔:

>> nums = '2.7183 3.1416 0.7071';
>> txt = 'asdf. blah, blah...';
>> contents = strjoin({nums,txt,nums,nums,txt},'n')
contents =
2.7183 3.1416 0.7071
asdf. blah, blah...
2.7183 3.1416 0.7071
2.7183 3.1416 0.7071
asdf. blah, blah...

使用str2double应用regexp,这将对单元数组进行操作:

>> str2double(reshape(regexp(contents,'(d+.?d*)','match'),3,[])')
ans =
2.7183    3.1416    0.7071
2.7183    3.1416    0.7071
2.7183    3.1416    0.7071

但是,数字必须在点之前有一个数字(例如1.),或者它将匹配不相关的字符串行中的点。

科学(指数)记数法

对于您的数据,其中数字看起来像-8.673617380E-19

fid = fopen('tBX70mRu.txt','r');
fullContents = char(fread(fid))'; fclose(fid); %' uint8 converted to string
pattern = '-?d*.d*E[+|-]d{2}';
allNums = str2double(reshape(regexp(fullContents,pattern,'match'),4,[])')

完美匹配。使用format longe验证。

经过大量修补,我想出了以下解决方案。 它首先将所有数据逐行读取到单元格数组中,然后逐行检查该单元格数组是否以数字或破折号开头(我的数据文件中所有所需的数字都这样做)并将其写入数组。

% Read in everything line-by-line
filename = 'data.dat';
fid = fopen(filename);
tline{1} = {fgets(fid)};
i = 1;
while ischar(tline{i}{1})
i = i + 1;
tline{i} = {fgets(fid)};
end
fclose(fid);
% Sift out number data
j = 1;
for i = 1:length(tline)
if ((isstrprop(tline{i}{1}(1),'digit')) || (strcmp(tline{i}{1}(1),'-')))
numberdata(j,:) = sscanf(tline{i}{1},'%f %f %f %f');
j = j + 1;
end
end

它有效,但我觉得这不是最佳的。

最新更新