Matlab: Find a string in a text file - matlab

I've searched around, bud didn't find a proper solution. So I ask it again.
There many lines in the .txt file. Looks Like this:
PRINT CONTENTS OF SUPERELEMENT yg_bde
PRINT OPTION = 3
HEADER =
8 55 2 12 6
13 0 13 11 0
1 1 0 0 1
0 0 1 78 14014
0 1584 166 103 yg_b
de 1561 0
922 931 1105 1121 1144
1158 1323 1503 0 989
1047 110005225 0 0 3
0 0
419 0 0 0 0
0 0 0 0
HEADER SUMMARY:
NUMBER OF ROWS = 55
NUMBER OF MATRICES = 2
NUMBER OF EDGE PLOT LINES = 12
NUMBER OF DEGREES OF FREEDOM PER NODE = 6
NUMBER OF DEGREE OF FREEDOM INDICES = 13
NUMBER OF NODES = 11
NUMBER OF LOAD VECTORS = 1
NUMBER OF TRANSFORMATIONS = 0
BASE FILE NAME= yg_bde
I need to locate the NUMBER OF ROWS = 55 and get the row number.
I think what need to do is
1. find and locate the Number of ROWS
2. Turn this line into number, so I can get the 55 number
I tried strfind(file ,string), but it can't return the line number, just the index when the file is in one line.
So, How can I Locate the NUMBER OF ROWS?
UPDATE:
whos data
Name Size Bytes Class Attributes
data 1x1 3094 struct

Approach #1
importdata based approach -
%// Import text data as a cell array with each cell holding each row of text data
data = importdata(inputfile,'\n') %// Edit inputfile to the path of your text file
%// Find the row(s) that holds the string 'NUMBER OF ROWS'
row_idx = find(~cellfun('isempty',strfind(data,'NUMBER OF ROWS')))
%// Find the number(s) in that/those row(s)
num = arrayfun(#(x) regexp(data{x}, '\d+', 'match'),row_idx)
Output I got -
row_idx =
19
num =
'55'
Now, num is a cell array. If you would like to have a numeric array, wrap it with str2double -
num_array = str2double(num)
Note: This also works if you have multiple lines with the string 'NUMBER OF ROWS'.
Approach #2
Alternative fgetl based approach that works by reading the text file line-by-line -
fid = fopen(inputfile); %// Edit inputfile to the path of your text file
tline = fgetl(fid);
num = [];
while ischar(tline)
if ~isempty(strfind(tline,'NUMBER OF ROWS'))
num = [num regexp(tline, '\d+', 'match')]; %#ok<AGROW>
end
tline = fgetl(fid);
end
fclose(fid);
num_array = str2double(num)

Related

MATLAB write string and then table to file

I need to write a string and a table to one text file. The string contains a description of the data in the table, but is not the headers for the table. I am using R2019a which I guess means the "Append" writetable option does not work? Please see my example data below:
% Load data
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
string = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
% How I tried to do this (which does not work!)
fid = fopen(filename, 'w', 'n');
fprintf(fid, '%s', cell2mat(string))
fclose(fid);
writetable(table, filename, 'FileType', 'text', 'WriteVariableNames', 0, 'Delimiter', 'tab', 'WriteMode', 'Append')
I get this error:
Error using writetable (line 155)
Wrong number of arguments.
Does anyone have a suggestion as to how to proceed?
Thanks!
A bit hacky, but here's an idea.
Convert your existing table to a cell array with table2cell.
Prepend a row of cells which consists of your string, followed by empty cells.
Convert the cell array back to a table with cell2table, and write the new table to the file.
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
s = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
new_table = cell2table([[s repmat({''},1,size(table,2)-1)] ; table2cell(table)]);
writetable(new_table,filename,'FileType','text','WriteVariableNames',0,'Delimiter','tab');
>> !head dummyoutput.sfc
This is a string about the cereal table
70 5 0.33 1 10 N 100% Bran 280
120 8 -1 5 2 Q 100% Natural Bran 135
70 7 0.33 1 9 K All-Bran 320
50 8 0.5 0 14 K All-Bran with Extra Fiber 330
110 14 0.75 2 1 R Almond Delight -1
110 10.5 0.75 2 1.5 G Apple Cinnamon Cheerios 70
110 11 1 0 1 K Apple Jacks 30
130 18 0.75 2 2 G Basic 4 100
90 15 0.67 1 4 R Bran Chex 125

Search and replace for a specific string in multiple lines of a text file in matlab

I have a text file in which I want to search for the number 255 in every line to replace it with the number 0. It is to be noted that the number are written in the text file as strings. I want to skip the first 13 lines, since there is text in these 13 lines.
A part of the text file is shown below:
F2G_DIM 3
F2G_VERSION 1
F2G_LOCATION 0 0 0.5
F2G_ROTATION 0
F2G_ORIGIN 0 0 0
F2G_NB_NODES 300 150 50
F2G_LAGS 10 10 1
F2G_ORDER +Y +X +Z
F2G_NB_VARIABLES 1
F2G_VARIABLE_1 Facies
F2G_UNDEFINED_1 255
F2G_VALUES
2
1
2
255
2
255
2
2
5
9
How can I solve this problem?
For your first questions you can use logical indexing to find and substitute the 255
pattern = 255; %Number to find
array = randi(10,10,1); %Some array
array([4,8,9]) = 255;
array(array==pattern) = 0; %Substitute values
For the second question, you can use dlmread to load in the data. It allows you to specify a header to ignore.
data = dlmread('file.csv',' ',13,0);
where 13 is the number of rows to ignore and 0 is the number of columns to ignore.
In total you have something like:
pattern = 255; %Pattern
data = dlmread('file.csv',' ',13,0); %Load
data(data==pattern) = 0; %Substitute values

Writing on an existing mixed numeric and string text file with different field

I have a mixed numeric and string text file with different fields divided by [ ]. Some of its content is like:
[JUNCTIONS]
;ID Elev Demand Pattern
2 0 0 ;
9 0 0 ;
5 0 11 ;
6 0 20 ;
[RESERVOIRS]
;ID Head Pattern
1 5 ;
4 50 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
66 2 9 1000 250 100 0 Open ;
2 9 4 1000 150 100 0 Open ;
3 9 5 1000 150 100 0 Open ;
4 2 6 1000 150 100 0 Open ;
I want to overwrite numeric variables below the columns "Demand" and "Roughness" from MATLAB.
Would you please help me. I read about the performance of import and export commands of Matlab, but I couldn't find the solution.
Here is a small script that will read all your data into a cell array. Each cell is a column of data. As Divakar said, make your data is vertically aligned or textscan will stop when one of the lines is not the same as the last.
fid = fopen(file,'r');
while 1
line=fgetl(fid);
if ~strcmp(line,'')
if ~isempty(strfind(line,'['))
% //Let's check it
start = strfind(line,'[');
split = strfind(line,']');
category = line(start+1:split-1);
if strcmp(category,'PIPES')
break;
end
end
end
end
% //skip the header line
line=fgetl(fid);
% //So now we're on the right line, let's read in the table.
data = textscan(fid,'%d %d %d %d %d %d %d %s');
fclose(fid);

How to skip lines in a txt file using Matlab?

I am working on a GUI program that involves uploading a txt file. The first 80 lines of the file contains information I do not need, it is a mix of numeric and text data. For example here is a few lines of the data I do not want to use;
vertical_line_flag;0
vertical_line_ratio;0
laser_wavelength;0
laser_powerlevel;0
overlay_js;0
Relative Intensity Correction Flag;0
Pixel;Wavelength;Wavenumber;Raman Shift;Dark;Reference;Raw data #1;Dark Subtracted #1;%TR #1;Absorbance #1;Irradiance (lumen) #1;
0;165.98;60247.73;-60247.73;0.0000;65535.0000;1125.0000;31.0000;0.0000;0.0000;0.0000;
1;166.38;60103.59;-60103.59;0.0000;65535.0000;549.0000;-545.0000;0.0000;0.0000;0.0000;
2;166.78;59960.14;-59960.14;0.0000;65535.0000;0.0000;-1094.0000;0.0000;0.0000;0.0000;
3;167.18;59817.38;-59817.38;0.0000;65535.0000;998.0000;-96.0000;0.0000;0.0000;0.0000;
4;167.57;59675.31;-59675.31;0.0000;65535.0000;1046.0000;-48.0000;0.0000;0.0000;0.0000;
5;167.97;59533.90;-59533.90;0.0000;65535.0000;1020.0000;-74.0000;0.0000;0.0000;0.0000;
6;168.37;59393.17;-59393.17;0.0000;65535.0000;1003.0000;-91.0000;0.0000;0.0000;0.0000;
7;168.77;59253.11;-59253.11;0.0000;65535.0000;1051.0000;-43.0000;0.0000;0.0000;0.0000;
8;169.17;59113.71;-59113.71;0.0000;65535.0000;1024.0000;-70.0000;0.0000;0.0000;0.0000;
9;169.56;58974.97;-58974.97;0.0000;65535.0000;1045.0000;-49.0000;0.0000;0.0000;0.0000;
10;169.96;58836.88;-58836.88;0.0000;65535.0000;1091.0000;-3.0000;0.0000;0.0000;0.0000;
11;170.36;58699.44;-58699.44;0.0000;65535.0000;1064.0000;-30.0000;0.0000;0.0000;0.0000;
12;170.76;58562.65;-58562.65;0.0000;65535.0000;1019.0000;-75.0000;0.0000;0.0000;0.0000;
The point where the numbers begin, as in the line after (lumen) #1; is the data that I want to use in my program.
I have tried using this code to skip the first 80 lines of the file
[FileName,PathName]= uigetfile('*.txt*','Files to Study');
file =fullfile(PathName,FileName);
fid = fopen(file);
A = textscan(fid,'%f' ,'HeaderLines',80);
but this results in A= [0x1 double]
Any suggestions on how to resolve this would be greatly appreciated.
The problem with your current use of textscan is that ; is not a default delimiter. So this will work:
fid = fopen(file);
A = textscan(fid,'%f' ,'HeaderLines',80,'Delimiter',';');
But if the rest of the file is 100% numerical then you can just use dlmread and set row and column values at which to start reading (note: unlike pretty much everything else in MATLAB, these start at zero).
For your test data:
A = dlmread('test.txt',';',7,0);
For the real data with 80 lines of header:
A = dlmread(filename,';',80,0);
Try this code:
A = [];
tline = fgets(fid);
while ischar(tline)
parts = textscan(tline, '%d;');
if numel(parts{1}) > 0
A = [ A ; parts{:}' ];
end
tline = fgets(fid);
end
fclose(fid);
Basically, it looks for lines with numerical values in the text file. For each one of these lines, scan the values and attach them as rows in matrix A.
The output I get with your text is:
A =
0 166 60248 -60248 0 65535 1125 31 0 0 0
1 166 60104 -60104 0 65535 549 -545 0 0 0
2 167 59960 -59960 0 65535 0 -1094 0 0 0
3 167 59817 -59817 0 65535 998 -96 0 0 0
4 168 59675 -59675 0 65535 1046 -48 0 0 0
5 168 59534 -59534 0 65535 1020 -74 0 0 0
...
Hope that it helps, Regards.

Grouping strings by matching substring

After running a SPICE simulation I get an .a2d file which I am parsing with Matlab. After parsing the file I get a cell array with the names of the variables
Ex: vars = {'s0';'s1';'s2';'a0';'a1'}
and a data matrix with the signals transitions, where each row represents the data of each signal and columns represent time. All the data is binary, i.e., it's only 0 or 1.
What I want to do is to create an algorithm that detects "words" based on the names stored in vars. For example, s0, s1, and s2 form a 3-bit word 's'; a0 and a1 a 2-bit word 'a'.
Finally, what I need is to break the data matrix into one array for each word (converting from binary to decimal).
I am doing that by hand, but I want to know if there is any way to do it by a script.
Here's a possible solution, putting the final values into the fields of a struct. I've used a regexp to extract the variable names and shifts as you didn't say how long they might be.
% fake data
vars = {'sums4', 'sums2', 'sums1', 'a0', 'a5'};
data(1,:) = logical([0 0 1 0 0 0 1]);
data(2,:) = logical([0 1 1 1 1 0 0]);
data(3,:) = logical([1 0 1 1 0 0 1]);
data(4,:) = logical([0 0 1 0 1 1 1]);
data(5,:) = logical([0 1 1 1 0 0 0]);
output = struct();
for i = 1:length(vars)
matches = regexp(vars{i}, '(\D+)(\d+)', 'tokens');
var = matches{1}{1};
shiftsize = str2num(matches{1}{2});
% initialise if not already present
if (~isfield(output, var))
output.(var) = zeros(1, size(data, 2));
end
% add apropriate shifted value to current values
output.(var) = output.(var) + (bitshift(1, shiftsize) * data(i, :));
end
output ends up with fields named after the string parts of vars
output =
sums: [2 4 22 6 4 0 18]
a: [0 32 33 32 1 1 1]