将参数从文本文件读入工作空间

时间:2013-06-03 15:53:52

标签: matlab text-parsing

我有一个文件,其中包含以下信息:

% ---------------------- location details --------------------------
%
% lat : latitude  [minimum = -90, maximum = 90, unit =  
%       degrees north]
% lon : longitude [ minimum = -360, maximum = 360, unit = 
%       deg east]
% z: altitude (above sea level, m)
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833

这是文件的一小部分。

我想将这些信息读入MATLAB,然后可以使用这些信息进行一些计算。我想要读入MATLAB的文件部分是文本文件中没有注释的部分,在行的开头有一个%,变量应该是然后保存在工作区中。例如,我想:

lat = 54.35
lon = -2.9833

在工作区中。

我该怎么做?我读过关于textscanfopen的内容,虽然在这种情况下这些似乎并不能帮助我。

4 个答案:

答案 0 :(得分:4)

快速而肮脏的方法

我能想到的最简单的解决方案是读取这个文件确实使用textscan :)并且由于这些行是用有效的MATLAB语法编写的,所以稍后可以使用eval来评估它们。首先将每一行读作一个字符串(忽略标题中的注释)

fid = fopen(filename);
C = textscan(fid, '%s', 'Delimiter', '', 'CommentStyle', '%')
fclose(fid);

然后将这些行逐个输入eval以在MATLAB工作区中创建变量:

cellfun(@eval, C{1});

这样做是将该行解释为MATLAB命令,创建文件中指定的变量并分配适当的值。如果您想要取消eval的输出,可以使用evalc代替“吸收输出”:

cellfun(@evalc, C{1}, 'UniformOutput', false);

这应该适用于您的基本示例,但如果您有任何参数的多个实例,它将失败。另请注意,eval家庭的速度非常慢。

更强大的方法

如果文件结构中的行具有parameter name = number模式,则可以更智能地读取行:

fid = fopen(filename);
C = textscan(fid, '%[^= ]%*[= ]%f', 'CommentStyle', '%')
fclose(fid);

模式中的%[^= ]与第一个字符匹配,直到第一个空格或等号。 %*[ =]忽略等号和任何尾随空格,然后数值与%f匹配。生成的单元格数组C将参数名称存储在第一个单元格中,并将其对应的值存储在第二个单元格中。

现在由您来操作已解析的数据。例如,要提取latlon的所有值,您可以执行以下操作:

lat = C{2}(strcmp(C{1}, 'lat'));
lon = C{2}(strcmp(C{1}, 'lon'));

如果您有多个“lat”行,lat将是一个包含所有这些值的数组。

答案 1 :(得分:0)

这是另一种快速而又肮脏的方式:

fp = fopen('foo.txt');

found = 1;
while ~feof(fp)
    line = fgetl(fp);
    if (line(1) ~= '%') && ischar(line)
        value(found) = sscanf(line,'%*s %*s %f');
        found = found + 1;
    end
end

%*s跳过'lat'或'long'和'='。

答案 2 :(得分:0)

您提供的示例有点表现良好,因此以下解决方案可能需要一些剪裁。但是,我建议针对任何eval()

% Read whole file ignoring lines that start with '%' and using '=' as delimiter
fid = fopen('test.txt');
s   = textscan(fid,'%s%f', 'CommentStyle','%','Delimiter','=');
fclose(fid);

% Identify lines with latitude and those with longitude
idxLat = strncmpi('lat',s{1},3);
idxLon = strncmpi('lon',s{1},3);

% Store all latitudes and longitudes
lat = s{2}(idxLat);
lon = s{2}(idxLon);

答案 3 :(得分:0)

获取一个字段名称与参数名称匹配的结构,接受以逗号分隔的列表。列出在char_params

中应保留为字符串的所有参数
char_params={};
fid = fopen(filename);
% Load lines into cell (1x1) containing cell array s (Nx1), 
% skipping lines starting with % and cutting off anything after % in a line
s   = textscan(fid,'%s', 'CommentStyle','%','Delimiter','%');
fclose(fid);
% access the lines strings s{1}, split across '=' and remove whitespace on     both sides
s=strtrim(split(s{1},'='));
% Interpret parameters and save to structure
for ind=1:length(s)
%    User says which parameters are strings
    if any(strcmpi(s{ind,1},char_params))
        file_struct.(s{ind,1})=s{ind,2};
    % Otherwise, assume they are numbers or numeric row arrays
    else
%         remove parentheses and brackets
        trim_s=regexprep(s(ind,2),'[[]()]','');
%         convert comma-separated lists into row arrays
        file_struct.(s{ind,1})=str2double(split(trim_s{1},',')).';
    end
end