Text-CSV_XS
view release on metacpan or search on metacpan
examples/csv-check view on Meta::CPAN
#!/pro/bin/perl
# csv-check: Check validity of CSV file and report
# (m)'20 [21 May 2020] Copyright H.M.Brand 2007-2025
# This code requires the defined-or feature and PerlIO
use 5.012000;
use warnings;
use Data::Peek;
use Encode qw( decode encode );
our $VERSION = "2.06"; # 2025-01-03
my $cmd = $0; $cmd =~ s{.*/}{};
sub usage {
my $err = shift and select STDERR;
print <<"EOU";
usage: $cmd [-s <sep>] [-q <quot>] [-e <esc>] [-u] [--pp] [file.csv]
-s S --sep=S use S as seperator char. Auto-detect, default = ','
the string "tab" is allowed.
-q Q --quo=Q use Q as quote char. Auto-detect, default = '"'
the string "undef" will disable quotation.
-e E --esc=E use E as escape char. Auto-detect, default = '"'
the string "undef" will disable escapes.
-N --nl force EOL to \\n
-C --cr force EOL to \\r
-M --crnl force EOL to \\r\\n
-u --utf-8 check if all fields are valid unicode
-E E --enc=E open file with encoding E
-h --hdr check with header (implies BOM)
-b --bom check with BOM (no header)
-f --skip-formula do not check formula's
--pp use Text::CSV_PP instead (cross-check)
-A a --attr=at:val pass attributes to parser
--at=val is also supported for know attributes
-L --list-attr list supported CSV attributes
-X --list-changes list attributes that changed from default
EOU
exit $err;
} # usage
use Getopt::Long qw(:config bundling passthrough);
my $eol;
GetOptions (
"help|?" => sub { usage (0); },
"V|version" => sub { say "$cmd [$VERSION]"; exit 0; },
"c|s|sep=s" => \(my $sep = ""),
"q|quo|quote=s" => \(my $quo = '"'),
"e|esc|escape=s" => \(my $esc = '"'),
"N|nl!" => sub { $eol = "\n"; },
"C|cr!" => sub { $eol = "\r"; },
"M|crnl!" => sub { $eol = "\r\n"; },
"B|binary!" => \(my $bin = 1),
"u|utf|utf8|utf-8!" => \(my $opt_u = 0),
"E|enc|encoding=s" => \(my $enc),
"h|hdr|header!" => \(my $opt_h = 0),
"b|bom!" => \(my $opt_b = 0),
"f|skip-formula!" => \(my $opt_f = 0),
"A|attr=s" => \ my @opt_A,
"L|list-attr!" => \ my $opt_L,
"X|list-changes!" => \ my $opt_X,
"pp!" => \(my $opt_p = 0),
"v|verbose:1" => \(my $opt_v = 0),
) or usage (1);
$opt_X and $opt_L++;
my $csvmod = "Text::CSV_XS";
if ($opt_p) {
require Text::CSV_PP;
$csvmod = "Text::CSV_PP";
}
else {
require Text::CSV_XS;
}
$csvmod->import ();
binmode STDOUT, ":encoding(utf-8)";
binmode STDERR, ":encoding(utf-8)";
my $fn = $ARGV[0] // "-";
my @warn;
my %csvarg = (
sep_char => $sep eq "tab" ? "\t" : $sep,
( run in 0.518 second using v1.01-cache-2.11-cpan-39bf76dae61 )