我有一个数据文件,由空格分隔的数字行(四列)组成,每隔一段时间就会有一些文本。 下面是一个示例数据文件。我想提取有四列数字的部分。
如何跳过文本并仅阅读数字? 我尝试使用文本扫描:
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
它有效,但我觉得这不是最佳的。