App-csvtool
view release on metacpan or search on metacpan
bin/csvtool view on Meta::CPAN
use Commandable::Finder::Packages 0.14;
use Text::CSV;
my $DELIM = ",";
sub new_csv
{
return Text::CSV->new({
binary => 1,
sep_char => $DELIM,
@_,
});
}
my $cinv = Commandable::Invocation->new_from_tokens( @ARGV );
my $tool = $cinv->pull_token // die "Need TOOL name\n";
my $finder = Commandable::Finder::Packages->new(
base => "App::csvtool",
named_by_package => 1,
);
$finder->configure( bundling => 1 );
$finder->add_global_options(
{ name => "d=", into => \$DELIM,
description => "Sets the field delimiter character" },
{ name => "tab", into => sub { $DELIM = "\t" },
description => "Sets the field delimiter character to tab (\\t)" },
);
$finder->handle_global_options( $cinv );
my $cmd = $finder->find_command( $tool ) or die "Unrecognised tool $tool\n";
my $toolpkg = $cmd->package;
my @args = $finder->parse_invocation( $cmd, $cinv );
$toolpkg or
exit $cmd->code->( @args );
@ARGV = ();
push @ARGV, $cinv->pull_token while defined $cinv->peek_token;
if( $toolpkg->can( "WANT_READER" ) and my $count = $toolpkg->WANT_READER ) {
# TODO: If count is some special token like "*", merge all the files into a
# single reader
foreach ( 1 .. $count ) {
my $path = shift @ARGV;
my $fh;
$path eq "-" ? $fh = \*STDIN
: open( $fh, "<", $path ) || die "Cannot read $path - $!";
my $csv = new_csv();
push @args, sub { $csv->getline( $fh ) };
}
}
if( $toolpkg->can( "WANT_OUTPUT" ) and $toolpkg->WANT_OUTPUT ) {
my $csv = new_csv( eol => $/ );
push @args, sub { $csv->print( \*STDOUT, $_[0] ) or die "Cannot print - $!" };
}
push @args, @ARGV;
$toolpkg->run( @args );
__END__
=head1 NAME
F<csvtool> - command-line tools for operating on CSV-formatted data
=head1 SYNOPSIS
$ csvtool COMMAND OPTS... INPUT...
=head1 DESCRIPTION
This tool provides several named sub-commands that act similarly to UNIX
commands of the same names, but operate on CSV-formatted data rather than
simple lines of text.
Input is taken from one or more files named on the commandline, and output is
printed to standard output using CSV formatting.
Columns in the data are named from 1 onwards. Thus, C<-f1> refers to the first
column of data, C<-f2> the second, and so on.
=head1 COMMANDS
=head2 cut
$ csvtool cut -fFIELDS INPUT...
Extracts the given field column(s).
=head3 --fields, -f
A comma-separated list of field indexes (defaults to 1).
=head2 grep
$ csvtool grep PATTERN INPUT...
Filter rows by the given pattern. The pattern is always interpreted as a Perl
regular expression.
=head3 --ignore-case, -i
Ignore case when matching.
=head3 --invert-match, -v
Output only the lines that do not match the filter pattern.
=head2 head
$ csvtool head -nLINES INPUT...
( run in 1.886 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )