PSSE_PARSE_LINE Reads and parses a single line from a PSS/E RAW data file [DATA, COMMENT] = PSSE_PARSE_LINE(FID) [DATA, COMMENT] = PSSE_PARSE_LINE(FID, TEMPLATE) [DATA, COMMENT] = PSSE_PARSE_LINE(STR) [DATA, COMMENT] = PSSE_PARSE_LINE(STR, TEMPLATE) Parses a single line from a PSS/E RAW data file, either directly read from the file, or passed as a string. Inputs: FID : (optional) file id of file from which to read the line STR : string containing the line to be parsed TEMPLATE : (optional) string of characters indicating how to interpret the type of the corresponding column, options are as follows: d, f or g : integer floating point number to be converted via SSCANF with %d, %f or %g, respectively. D, F or G : integer floating point number, possibly enclosed in single or double quotes, to be converted via SSCANF with %d, %f or %g, respectively. c or s : character or string, possibly enclosed in single or double quotes, which are stripped from the string Note: Data columns in STR that have no valid corresponding entry in TEMPLATE (beyond end of TEMPLATE, or a character other than those listed, e.g. '.') are returned as a string with no conversion. TEMPLATE entries for which there is no corresponding column are returned as NaN or empty string, depending on the type. Outputs: DATA : a cell array whose elements contain the contents of the corresponding column in the data, converted according to the TEMPLATE. COMMENT : (optional) possible comment at the end of the line
0001 function [data, comment] = psse_parse_line(str, t) 0002 %PSSE_PARSE_LINE Reads and parses a single line from a PSS/E RAW data file 0003 % [DATA, COMMENT] = PSSE_PARSE_LINE(FID) 0004 % [DATA, COMMENT] = PSSE_PARSE_LINE(FID, TEMPLATE) 0005 % [DATA, COMMENT] = PSSE_PARSE_LINE(STR) 0006 % [DATA, COMMENT] = PSSE_PARSE_LINE(STR, TEMPLATE) 0007 % 0008 % Parses a single line from a PSS/E RAW data file, either directly read 0009 % from the file, or passed as a string. 0010 % 0011 % Inputs: 0012 % FID : (optional) file id of file from which to read the line 0013 % STR : string containing the line to be parsed 0014 % TEMPLATE : (optional) string of characters indicating how to 0015 % interpret the type of the corresponding column, options 0016 % are as follows: 0017 % d, f or g : integer floating point number to be converted 0018 % via SSCANF with %d, %f or %g, respectively. 0019 % D, F or G : integer floating point number, possibly enclosed 0020 % in single or double quotes, to be converted via 0021 % SSCANF with %d, %f or %g, respectively. 0022 % c or s : character or string, possibly enclosed in single 0023 % or double quotes, which are stripped from the string 0024 % Note: Data columns in STR that have no valid corresponding 0025 % entry in TEMPLATE (beyond end of TEMPLATE, or a character 0026 % other than those listed, e.g. '.') are returned as a 0027 % string with no conversion. TEMPLATE entries for which 0028 % there is no corresponding column are returned as NaN or 0029 % empty string, depending on the type. 0030 % Outputs: 0031 % DATA : a cell array whose elements contain the contents of 0032 % the corresponding column in the data, converted 0033 % according to the TEMPLATE. 0034 % COMMENT : (optional) possible comment at the end of the line 0035 0036 % MATPOWER 0037 % Copyright (c) 2014-2016, Power Systems Engineering Research Center (PSERC) 0038 % by Ray Zimmerman, PSERC Cornell 0039 % 0040 % This file is part of MATPOWER. 0041 % Covered by the 3-clause BSD License (see LICENSE file for details). 0042 % See https://matpower.org for more info. 0043 0044 %% read the line 0045 if ischar(str) 0046 ln = str; 0047 else 0048 ln = fgets(str); 0049 end 0050 0051 if ischar(ln) 0052 %% parse the line 0053 delim = '\s*(,|\s)\s*'; %% general delimiter 0054 repeatdelim = '\s*,\s*|\t'; %% delimiter that allows repeated delimiters 0055 non_quote_field = '[^''",\s/]+'; 0056 single_quote_field = '''([^'']|'''')*'''; 0057 double_quote_field = '"([^"]|"")*"'; 0058 any_field = sprintf('(?<col>%s|%s|%s)', non_quote_field, single_quote_field, double_quote_field); 0059 pat = sprintf('%s%s|%s|%s|(?<comment>/.*)?', any_field, delim, repeatdelim, any_field); 0060 % pat = '(?<col>[^''",\s/]+|''([^'']|'''')*''|"([^"]|"")*")\s*(,|\s)\s*|\s*,\s*|\t|(?<col>[^''",\s/]+|''([^'']|'''')*''|"([^"]|"")*")|(?<comment>/.*)?'; 0061 n = regexp(ln, pat, 'names'); 0062 0063 %% extract data 0064 if have_fcn('octave') && have_fcn('octave', 'vnum') < 4.003 0065 nc = length(n.col); 0066 if nc && isempty(n.col{nc}) 0067 data = n.col(1:nc-1); 0068 if ~isempty(n.comment{nc}) 0069 comment = strtrim(n.comment{nc}(2:end)); 0070 else 0071 comment = ''; 0072 end 0073 nc = nc - 1; 0074 else 0075 data = n.col; 0076 comment = ''; 0077 end 0078 else 0079 nc = length(n); 0080 if nc && isempty(n(nc).col) 0081 [data{1:nc-1}] = deal(n(1:nc-1).col); 0082 if ~isempty(n(nc).comment) 0083 comment = strtrim(n(nc).comment(2:end)); 0084 else 0085 comment = ''; 0086 end 0087 nc = nc - 1; 0088 else 0089 [data{1:nc}] = deal(n.col); 0090 comment = ''; 0091 end 0092 end 0093 0094 %% check for section end and Q record 0095 if length(data) == 1 && length(data{1}) == 1 0096 if data{1}(1) == '0' 0097 data{1} = 0; 0098 elseif data{1}(1) == 'Q' 0099 data = {}; 0100 end 0101 end 0102 else 0103 data = {}; 0104 comment = ''; 0105 end 0106 0107 %% clean/convert data (convert numeric, strip quotes from strings) 0108 if nargin > 1 && ~isempty(t) && ~isempty(data) && ... 0109 (length(data) ~= 1 || ~isnumeric(data{1}) || data{1} ~= 0) 0110 nt = length(t); 0111 for k = 1:min(nc, nt) 0112 switch t(k) 0113 case {'D', 'F', 'G', 's', 'c'} 0114 if ~isempty(data{k}) && (data{k}(1) == '''' || data{k}(1) == '"') 0115 data{k} = data{k}(2:end-1); 0116 end 0117 % otherwise %% do nothing 0118 end 0119 switch upper(t(k)) 0120 case {'D', 'F', 'G'} 0121 data{k} = sscanf(data{k}, ['%' lower(t(k))]); 0122 % otherwise %% do nothing 0123 end 0124 end 0125 if nc < nt 0126 data(nc+1:nt) = cell(1,nt-nc); 0127 end 0128 end