matlab将不同长度的变量读入工作区

matlab将不同长度的变量读入工作区,matlab,fopen,Matlab,Fopen,这是我们的后续问题 我想知道,我将如何阅读以下内容: % ---------------------- details -------------------------- %--------------------------------------------------------------- % location: lat = 54.35 lon = -2.9833 % % ---------------------- details -----------------

这是我们的后续问题

我想知道,我将如何阅读以下内容:

% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833
%
% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833
   heights = 0, 2, 4, 7, 10, 13, 16, 19, 22, 25, 30, 35
   Volume = 6197333, 5630000, 4958800, 4419400, 3880000, 3340600,   
        3146800, 2780200, 2413600, 2177000, 1696000, 811000
%
Eitan T建议使用:

fid = fopen(filename);
C = textscan(fid, '%[^= ]%*[= ]%f', 'CommentStyle', '%')
fclose(fid);
从文件中获取信息,然后

lat = C{2}(strcmp(C{1}, 'lat'));
lon = C{2}(strcmp(C{1}, 'lon'));
获取相关参数。我如何将其改为以下内容:

% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833
%
% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833
   heights = 0, 2, 4, 7, 10, 13, 16, 19, 22, 25, 30, 35
   Volume = 6197333, 5630000, 4958800, 4419400, 3880000, 3340600,   
        3146800, 2780200, 2413600, 2177000, 1696000, 811000
%
其中变量应包含等号后的所有数据点(直到下一个变量开始,在本例中为体积)


感谢您的帮助

这里有一个方法,它使用一些肮脏的字符串黑客和
eval
来获得结果。这适用于您的示例,但我不推荐:

fid = fopen('data.txt');
contents = textscan(fid, '%s', 'CommentStyle', '%', 'Delimiter', '\n');
contents = contents{1};

for ii = 1:length(contents)
  line = contents{ii};
  eval( [strrep(line, '=', '=['), '];'] ) # convert to valid Matlab syntax
end
更好的方法是使用
textscan

for ii = 1:length(contents)
  idx = strfind(contents{ii}, ' = ');
  vars{ii} = contents{ii}(1:idx-1);
  vals(ii) = textscan(contents{ii}(idx+3:end), '%f', 'Delimiter', ',');
end
现在变量
vars
vals
具有变量的名称及其值。要提取值,可以执行以下操作

ix = strmatch('lat', vars, 'exact');
lat = vals{ix};

ix = strmatch('lon', vars, 'exact');
lon = vals{ix};

ix = strmatch('heights', vars, 'exact');
heights = vals{ix};

ix = strmatch('Volume', vars, 'exact');
volume = vals{ix};

这里有一种方法,它使用一些肮脏的字符串黑客和
eval
来获得结果。这适用于您的示例,但我不推荐:

fid = fopen('data.txt');
contents = textscan(fid, '%s', 'CommentStyle', '%', 'Delimiter', '\n');
contents = contents{1};

for ii = 1:length(contents)
  line = contents{ii};
  eval( [strrep(line, '=', '=['), '];'] ) # convert to valid Matlab syntax
end
更好的方法是使用
textscan

for ii = 1:length(contents)
  idx = strfind(contents{ii}, ' = ');
  vars{ii} = contents{ii}(1:idx-1);
  vals(ii) = textscan(contents{ii}(idx+3:end), '%f', 'Delimiter', ',');
end
现在变量
vars
vals
具有变量的名称及其值。要提取值,可以执行以下操作

ix = strmatch('lat', vars, 'exact');
lat = vals{ix};

ix = strmatch('lon', vars, 'exact');
lon = vals{ix};

ix = strmatch('heights', vars, 'exact');
heights = vals{ix};

ix = strmatch('Volume', vars, 'exact');
volume = vals{ix};

这可以通过两步方法完成:

  • 读取前导字符串(第一个元素)、等号(忽略),并将行的其余部分作为字符串(第二个元素)
  • 将其余行的这些字符串转换为浮点数(第二个元素)
  • 然而,这里有一个小小的缺点;你的台词似乎遵循两种格式;一个是步骤1)中描述的,另一个是前一行的延续,其中包含数字

    因此,需要额外的步骤:

  • 读取前导字符串(第一个元素)、等号(忽略),并将行的其余部分作为字符串(第二个元素)
  • 当遇到“其他格式”时,此操作将失败。检测此问题,更正此问题,然后继续
  • 将其余行的这些字符串转换为浮点数(第二个元素)
  • 我认为这会起作用:

    fid = fopen('data.txt');
    
    C = [];
    try
        while ~feof(fid)
    
            % Read next set of data, assuming the "first format"
            C_new = textscan(fid, '%[^= ]%*[= ]%s', 'CommentStyle', '%', 'Delimiter', '');
            C     = [C; C_new]; %#ok
    
            % When we have non-trivial data, check for the "second format"
            if ~all(cellfun('isempty', C_new))
    
                % Second format detected!
                if ~feof(fid)
    
                    % get the line manually
                    D = fgetl(fid);
                    % Insert new data from fgetl
                    C{2}(end) = {[C{2}{end} C{1}{end} D]};
                    % Correct the cell
                    C{1}(end) = [];
    
                end
    
            else
                % empty means we've reached the end
                C = C(1:end-1,:);
    
            end
    
        end
        fclose(fid);
    
    catch ME
        % Just to make sure to not have any file handles lingering about
        fclose(fid);
        throw(ME);
    
    end
    
    % convert second elements to floats
    C{2} = cellfun(@str2num, C{2}, 'UniformOutput', false);
    

    这可以通过两步方法完成:

  • 读取前导字符串(第一个元素)、等号(忽略),并将行的其余部分作为字符串(第二个元素)
  • 将其余行的这些字符串转换为浮点数(第二个元素)
  • 然而,这里有一个小小的缺点;你的台词似乎遵循两种格式;一个是步骤1)中描述的,另一个是前一行的延续,其中包含数字

    因此,需要额外的步骤:

  • 读取前导字符串(第一个元素)、等号(忽略),并将行的其余部分作为字符串(第二个元素)
  • 当遇到“其他格式”时,此操作将失败。检测此问题,更正此问题,然后继续
  • 将其余行的这些字符串转换为浮点数(第二个元素)
  • 我认为这会起作用:

    fid = fopen('data.txt');
    
    C = [];
    try
        while ~feof(fid)
    
            % Read next set of data, assuming the "first format"
            C_new = textscan(fid, '%[^= ]%*[= ]%s', 'CommentStyle', '%', 'Delimiter', '');
            C     = [C; C_new]; %#ok
    
            % When we have non-trivial data, check for the "second format"
            if ~all(cellfun('isempty', C_new))
    
                % Second format detected!
                if ~feof(fid)
    
                    % get the line manually
                    D = fgetl(fid);
                    % Insert new data from fgetl
                    C{2}(end) = {[C{2}{end} C{1}{end} D]};
                    % Correct the cell
                    C{1}(end) = [];
    
                end
    
            else
                % empty means we've reached the end
                C = C(1:end-1,:);
    
            end
    
        end
        fclose(fid);
    
    catch ME
        % Just to make sure to not have any file handles lingering about
        fclose(fid);
        throw(ME);
    
    end
    
    % convert second elements to floats
    C{2} = cellfun(@str2num, C{2}, 'UniformOutput', false);
    

    如果你能摆脱多行体积行,你写的是有效的matlab。因此,只需使用命令将参数文件作为matlab脚本调用即可


    正如其他人所展示的,您唯一的其他选择是编写最终看起来像一个卑鄙的Matlab解析器的东西。绝对有更好的方法来消磨你的时间

    如果你能摆脱多行体积行,你所写的是有效的matlab。因此,只需使用命令将参数文件作为matlab脚本调用即可


    正如其他人所展示的,您唯一的其他选择是编写最终看起来像一个卑鄙的Matlab解析器的东西。绝对有更好的方法来消磨你的时间

    Volume
    的数据实际上是多行的,还是您在这个问题中就是这样写的?我会用
    textscan()
    regexp()
    读取整个文件,然后用
    str2double()
    进行转换。我没有举任何例子,因为从我之前的回答中,我没有得到任何关于您的文件是否表现良好的反馈,现在这是一个后续问题,可能还有更多问题,直到您展示关于您拥有的文件的全部内容以及您需要从中获得的信息。
    Volume
    的数据实际上是多行的,或者在这个问题中你是这样写的吗?我会用
    textscan()
    regexp()
    读取整个文件,然后用
    str2double()
    进行转换。我没有举任何例子,因为从我之前的回答中,我没有得到任何关于您的文件是否表现良好的反馈,现在这是一个后续问题,可能还有更多问题,直到您展示您所拥有的文件的全部内容以及您需要从中获得什么。