1#!/pro/bin/perl
2
3use strict;
4use warnings;
5
6# rewrite.pl: Convert csv to csv
7#	   (m)'17 [20 Sep 2017] Copyright H.M.Brand 2014-2021
8
9our $VERSION = "0.05 - 20170920";
10
11sub usage {
12    my $err = shift and select STDERR;
13    print <<"EOH";
14usage: $0 [-o file] [-s S] [-m] [-c] [-i] [file]
15    -o F  --out=F     output to file F (default STDOUT)
16    -s S  --sep=S     set input separator to S (default ; , TAB or |)
17    -m    --ms        output Dutch style MicroSoft CSV (; and \\r\\n)
18    -n    --no-header CSV has no header line. If selected
19                      - default input sep = ;
20                      - BOM is not used/recognized
21    -c    --confuse   Use confusing separation and quoting characters
22    -i    --invisible Use invisible separation and quotation sequences
23EOH
24    exit $err;
25    } # usage
26
27use Getopt::Long qw(:config bundling);
28GetOptions (
29    "help|?"		=> sub { usage (0); },
30    "s|sep=s"		=> \my $in_sep,
31    "m|ms!"		=> \my $ms,
32    "c|confuse!"	=> \my $confuse,
33    "i|invisible!"	=> \my $invis,
34    "n|no-header!"	=> \my $opt_n,
35    "o|out=s"		=> \my $opt_o,
36    ) or usage (1);
37$invis and $confuse++;
38
39use Text::CSV_XS qw( csv );
40
41# U+0022 "	QUOTATION MARK			"
42# U+002c ,	COMMA				,
43# U+037e ;	GREEK QUESTION MARK		;
44# U+201a ‚	SINGLE LOW-9 QUOTATION MARK	,
45# U+2033 ″	DOUBLE PRIME			"
46# U+2063	INVISIBLE SEPARATOR
47
48my $io  = shift || \*DATA;
49my $eol = $ms ? "\r\n" : "\n";
50my $sep = $confuse ? $ms ? "\x{037e}" : $invis ? "\x{2063}" : "\x{201a}"
51		   : $ms ? ";" : ",";
52my $quo = $confuse ? "\x{2033}" : '"';
53
54binmode STDOUT, ":encoding(utf-8)";
55
56my @hdr;
57my @opt_i = (in  => $io);
58my @opt_o = (out => \*STDOUT, eol => $eol, sep => $sep, quo => $quo);
59if ($opt_n) {
60    push @opt_i,
61	sep          => $in_sep // ";";
62    }
63else {
64    push @opt_i,
65	bom          => 1,
66	sep_set      => [ $in_sep ? $in_sep : (";", ",", "|", "\t") ],
67	keep_headers => \@hdr;
68    push @opt_o,
69	headers      => \@hdr;
70    }
71csv (in => csv (@opt_i), @opt_o);
72
73__END__
74a;b;c;d;e;f
751;2;3;4;5;6
762;3;4;5;6;7
773;4;5;6;7;8
784;5;6;7;8;9
79