Parsing a file with nonstandard format
조회 수: 2 (최근 30일)
이전 댓글 표시
Lets say I need to get data out of a file but I can't count on the exact format of the entire file. All I can count on is the data immediately preceding or following the data I need. In particular lets say this text exists somewhere in the file "<x>45.234</x>" and what I need is that number. It might be in its own line, or not. It might have stuff around it, or not. And there are an unknown number of these datapoints in the file. How do I read all such numbers into an array, in the order they appear? Example file attached
댓글 수: 0
채택된 답변
Walter Roberson
2016년 3월 6일
filecontent = fileread('YourFileName.txt');
xval_string = regexp(filecontent, '(?<=<x>)-?[0-9.]+(?=<x>)', 'match');
xval = str2double(xval_string);
This accounts for a possible negative sign immediately before the number, but otherwise restricts numbers to being composed of digits and '.' . It does not do good verification on numbers, and would (for example) cheerfully accept '134.8..171.9.' . It can be improved, but before that is done it would be best to have documentation on exactly what forms a "number" is permitted to take. Spaces after leading minus? Unary plus permitted? For numbers with absolute magnitude less than 1, can the leading 0 be omitted? Exponential format permitted? Which characters can be in the exponent operator? How many digits of exponent? Is '.' permitted immediately before the exponent character or will there always be a digit before the exponent character? And so on.
댓글 수: 2
Walter Roberson
2016년 3월 6일
I missed the '/'
filecontent = fileread('test3.txt');
xval_strings = regexp(filecontent, '(?<=<x>)-?\d+(.\d+)?(?=</x>)', 'match');
xvals = str2double(xval_strings);
Note that this will get all of the x values without paying attention to which mesh the values are in.
I recommend that you use xmlread() to parse this.
%all item numbering in XML is 0 based
doc = xmlread('test3.xml');
doc_objects = doc.getElementsByTagName('object');
num_obj = doc_objects.getLength;
obj_struct(num_obj) = struct('id', [], 'xyz', []); %pre-allocate
for obj_num = 1 : num_obj
this_obj = doc_objects.item(obj_num - 1);
obj_id = str2double(this_obj.getAttribute('id'));
obj_struct(obj_num).id = obj_id;
this_mesh = this_obj.getElementsByTagName('mesh').item(0);
these_x = this_mesh.getElementsByTagName('x');
num_x = these_x.getLength;
xyz = zeros(num_x, 3);
for xidx = 1 : num_x
this_x = these_x.item(xidx-1);
x_str = this_x.item(0).getData;
this_y = this_x.getNextSibling;
y_str = this_y.item(0).getData;
this_z = this_y.getNextSibling;
z_str = this_z.item(0).getData;
xyz(xidx,:) = str2double({x_str, y_str, z_str});
end
obj_struct(obj_num).xyz = xyz;
end
This will return a struct with two fields for every object, 'id' and 'xyz' where xyz is an N x 3 array of the x, y, z coordinates. I make the assumption that there will be exactly 1 mesh per object.
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 String Parsing에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!