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