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 )