From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

{
$App::PipeFilter::JsonSort::VERSION = '0.005';
}
use Moose;
with qw(
App::PipeFilter::Role::Input::Json
App::PipeFilter::Role::Writer::Print
App::PipeFilter::Role::Transform::None
);
has k => (
is => 'rw',
isa => 'ArrayRef',
default => sub { die "requires one or more -k flag" },
lazy => 1,
documentation => 'key fields to sort on',
);
has n => (
is => 'rw',
isa => 'Bool',
default => 0,
documentation => 'sort fields numerically',
);
has r => (
is => 'rw',
isa => 'Bool',
default => 0,
documentation => 'reverse sort order',
);
my @preferred_path = qw(
/bin
/usr/bin
/sbin
/usr/sbin
);
has sort => (
is => 'rw',
isa => 'Str',
lazy => 1,
documentation => 'sort(1) command to use',
default => sub {
my $self = shift();
foreach (@preferred_path) {
return "$_/sort" if -e "$_/sort";
}
return "/usr/bin/env sort";
},
);
has cut => (
is => 'rw',
isa => 'Str',
lazy => 1,
documentation => 'cut(1) command to use',
default => sub {
my $self = shift();
foreach (@preferred_path) {
return "$_/cut" if -e "$_/cut";
}
return "/usr/bin/env cut";
},
);
sub open_output {
my ($self, $filename) = @_;
my $sort = (
$self->sort() .
" -t '\t'" .
($self->n() ? ' -n' : '') .
($self->r() ? ' -r' : '') .
' | ' . $self->cut() . ' -f ' . (scalar(@{$self->k()}) + 1) . '-' .
(
($filename eq '-')
? ''
: " > $filename"
)
);
open my $fh, '|-', $sort or die "Can't pipe into sort: $!";
return $fh;
}
sub encode_output {
my $self = shift();
my @fields = @{$self->k()};
return map {
my %sortable;
@sortable{@fields} = @{$_}{@fields};
join("\t", @sortable{@fields}, encode_json($_)) . "\n";
} @_;
}
1;
__END__
=pod
=head1 NAME
App::PipeFilter::JsonSort - a sort(1)-like filter that understands JSON fields
=head1 VERSION
version 0.005
=head1 SYNOPSIS
Here is the jsort(1) pipeline filter.
#!/usr/bin/perl
use App::PipeFilter::JsonSort;
exit App::PipeFilter::JsonSort->new_with_options()->run();
=head1 DESCRIPTION
App::PipeFilter::JsonSort implements a pipeline filter similar to
sort(1), except that the -k flags describe JSON fields rather than
whitespace-separated columns.
This filter currently provides a small subset of the options that
sort(1) does.
=head1 PUBLIC ATTRIBUTES
This filter uses sort(1) and cut(1) to do most of its work.
=head2 k
The k() attribute names one or more key JSON fields to sort by. It is
analogous to the -k flag for sort(1). MooseX::Getopt sets k() to the
values of the -k options from the command line.
=head2 n
The boolean n() attribute (set by the -n command line flag) tells
App::PipeFilter::JsonSort to sort numerically. It sorts
lexicographically by default.
If specified, -n is passed to sort(1).
=head2 r
The boolean r() attribute (set by the -r command line flag) instructs
App::PipeFilter::JsonSort to reverse the sort.
If spedified, -r is passed to sort(1).
=head1 PUBLIC METHODS
=head2 encode_output
encode_output() prepeands JSON records with the values of their key
fields in tab-separated form. This output will be piped through
sort(1) to do the actual sorting, and through cut(1) to remove the
tab-separated sorting columns.
=head2 open_output
open_output() opens output through sort(1) and cut(1). It's a huge
cheat, but it works for simple cases.
=head1 SEE ALSO
You may read this module's implementation in its entirety at
perldoc -m App::PipeFilter::JsonSort
This class subclasses L<App::PipeFilter::Generic::Generic>. It is
customized with L<App::PipeFilter::Role::Reader::Sysread>,
L<App::PipeFilter::Role::Input::Json> and
L<App::PipeFilter::Role::Transform::None>.
L<App::PipeFilter> has top-level documentation including a table of
contents for all the libraries and utilities included in the project.
=head1 BUGS
=head1 REPOSITORY
=head1 COPYRIGHT AND LICENSE
App::PipeFilter::JsonSort
is Copyright 2011 by Rocco Caputo.
All rights are reserved.
App::PipeFilter::JsonSort
is released under the same terms as Perl itself.
=cut
# vim: ts=2 sw=2 expandtab