这是一个完整的解决方案(类似于@Marc描述的):
%# read lines
fid = fopen('file.txt','rt');
C = textscan(fid, '%s', 'Delimiter',''); C = C{1};
fclose(fid);
%# start/end of each structure
startIdx = find(ismember(C, 'struct'));
endIdx = find(ismember(C, 'endstruct'));
%# array of strucutres
N = numel(startIdx);
arr = struct('studentname','', 'notes','', 'n1',0, 'n2',0, 'average',0);
arr = repmat(arr,[N 1]);
%# parse and store each structure in the array
for i=1:numel(startIdx)
%# parse key/value of struct
s = C(startIdx(i)+1:endIdx(i)-1);
s = regexp(s, '(\w+)\s*[:=]\s*([^%$]*)(?:%[^$]*)?', 'tokens', 'once');
s = vertcat(s{:});
%# try to parse as numbers
v = str2double(s(:,2));
s(~isnan(v),2) = num2cell(v(~isnan(v)));
%# store: struct.key = value
for j=1:size(s,1)
arr(i).(s{j,1}) = s{j,2};
end
end
结果:
>> arr(1)
ans =
studentname: 'joe'
notes: ''
n1: 1.3
n2: 2
average: 1.7
>> arr(2)
ans =
studentname: 'marc'
notes: ''
n1: 2.3
n2: 3
average: 2.7
当然这是假设文件格式正确(struct/endstruct 块,所有结构都包含相同的字段,并且字段类型是一致的)
解释:
代码首先将文件行读入一个元胞数组。然后我们寻找 struct/endstruct 结构的开始/结束位置。我们用一些默认值初始化一个空的结构数组,并遍历文件解析每个块,并将该信息存储在一个结构中。
接下来我们使用正则 表达式来检测以下模式:
some_key_name = some value % optional comment here
我们允许空间中的一些变化,并且也接受两者之间的任何一个=
或:
作为字符。我们在正则表达式中使用捕获标记来恢复上述每个组件,并将它们存储在一个临时元胞数组中。此时,所有内容都存储为字符串。
现在实际值可以是数字或字符串。我们最初尝试使用 STR2DOUBLE 将它们解析为数字。NaN
如果失败,此函数将返回,我们使用它仅更改成功转换的部分。
最后有了上面的结果,我们使用动态的字段名将每个值存储在结构体数组中对应的键中。