Skip to content

Instantly share code, notes, and snippets.

@KrisKusano
Last active August 29, 2015 14:05
Show Gist options
  • Select an option

  • Save KrisKusano/eaad402812c089d9912a to your computer and use it in GitHub Desktop.

Select an option

Save KrisKusano/eaad402812c089d9912a to your computer and use it in GitHub Desktop.
wrap all strings in table that contain a delimiter with a quote character
function tableout = quote_delim_table(tablein, delimiter, varargin)
%% wrap all strings in table that contain a delimiter with a quote character
% SYNTAX
% tableout = quote_delim_table(tablein, delimiter)
% tableout = quote_delim_table(tablein, delimiter, quotechar)
%
% DESCRIPTION
% tableout = quote_delim_table(tablein, delimiter) all character columns in
% tablein, and wraps strings containing delimiter with a double quote ('"')
%
% tableout = quote_delim_table(tablein, delimiter, quotechar) wraps all strings
% with delimiter with the single character in quotechar
%
% NOTES
% If the string contains the quote character, replace with double quotes and
% also wrap the line in quotes
% EXAMPLES
% t = cell2table([num2cell(1:3)', num2cell(6:8)', {'OK comment'; 'bad, comment'; 'Also "trouble"'}],...
% 'VariableNames', {'x', 'y', 'notes'})
% % x y notes
% % _ _ ________________
% %
% % 1 6 'OK comment'
% % 2 7 'bad, comment'
% % 3 8 'Also "trouble"'
%
% writetable(t, 'bad.csv',...
% 'delimiter', ',')
% % % File contents:
% % x,y,notes
% % 1,6,OK comment
% % 2,7,bad, comment
% % 3,8,Also "trouble"
%
% tin = readtable('bad.csv',...
% 'delimiter', ',')
% % causes an error!
% % Delimiter on line 2 confuses it
% % Also, the trailing quote on last line would be cut off on read in
%
% tfixed = quote_delim_table(t, ',')
% % x y notes
% % _ _ ____________________
% %
% % 1 6 'OK comment'
% % 2 7 '"bad, comment"'
% % 3 8 '"Also ""trouble"""'
%
% writetable(tfixed, 'bad_fixed.csv',...
% 'delimiter', ',')
%
% tfin = readtable('bad_fixed.csv',...
% 'delimiter', ',')
% % x y notes
% % _ _ ________________
% %
% % 1 6 'OK comment'
% % 2 7 'bad, comment'
% % 3 8 'Also "trouble"'
%% check
if ~ischar(delimiter) || length(delimiter) ~= 1
error('quote_delim_table:DelimArg',...
'Delimiter argument ''%s'' is invalid. Must be char of length 1', delimiter);
end
%% quote char
if ~isempty(varargin)
if ischar(varargin{1}) && length(varargin) == 1
quotechar = varargin{1};
else
error('quote_delim_table:QuoteArg',...
'Quote argument ''%s'' is invalid. Must be char of length 1', varargin{1});
end
else
quotechar = '"'; % default
end
%% find char columns
tstruct = table2struct(tablein);
vnames = fieldnames(tstruct);
nv = length(vnames);
vchar = false(1, nv); % is the variable a character?
for i = 1:nv
if strcmp(class([tstruct.(vnames{i})]), 'char') % warns, but ischar does not work here
vchar(i) = true;
end
end
vchar = find(vchar);
%% Apply quotes
nq = length(vchar);
for i = 1:nq
col = table2cell(tablein(:, vchar(i)));
% replace empty cell with empty string
idx_empty = cellfun(@isempty, col);
col(idx_empty) = {''};
% replace quote character with double quote
col = cellfun(@(x) strrep(x, quotechar, [quotechar, quotechar]), col,...
'uni', false);
% look for delimiter, or quote, wrap in quote
idx_delim = ~cellfun(@isempty, regexp(col, [',|', quotechar], 'once'));
col(idx_delim) = cellfun(@(x) [quotechar, x, quotechar], col(idx_delim),...
'uni', false);
tablein(:, vchar(i)) = col;
end
%% done
tableout = tablein;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment