App-pltest

 view release on metacpan or  search on metacpan

pod/examples.pod  view on Meta::CPAN

=head1 NAME

pltest-examples - Perl One-Liner Examples

=head1 EXAMPLES

I<To steal ideas from one person is plagiarism.  To steal from many is research. ;-)>

Here's a wide variety of examples, many solving real-life problems.  Often you
can copy & paste them as-is.  Or you need to make minor changes, e.g. to adapt
them to your search expression.  Many of these examples started out quite
small, illustrating the power of pltest.  But in order to be generally useful,
they have been extended to cope with border cases.  See L<canned
commands|canned-commands> for how you can make your favourite ones easier to
use.

Only some of these are original.  Many have been adapted from the various Perl
one-liner webpages
(L<Tom Christiansen|http://softpanorama.org/Scripting/Perlorama/One-liners/tom_christiansen_one-liners.shtml>,
L<Peteris Krumins|https://nostarch.com/perloneliners>,
L<CatOnMat|https://catonmat.net/introduction-to-perl-one-liners>,
L<joyrexus|https://gist.github.com/joyrexus/7328094>,
L<Richard Socher|http://kiswebformations.wordpress.com/2015/04/04/perl-scripts-and-one-liners/>,
L<eduonix|https://blog.eduonix.com/perl-programming/learn-one-liners-perl-programming/>,
L<IBM 101|http://calmar.ws/linux/perl/One-liners101.html>,
L<IBM 102|https://www.ibm.com/developerworks/library/l-p102/>,
L<Oracle|https://blogs.oracle.com/linux/the-top-10-tricks-of-perl-one-liners-v2>,
L<PerlMonks|https://perlmonks.org/?node_id=502261>,
L<perloneliner|https://twitter.com/perloneliner>)
or videos
(L<Walt Mankowski|https://youtu.be/IGe0GnlIWq4>,
L<Techalicious|https://youtu.be/gbZAABq4uZk?t=284>,
L<David Oswald|https://youtu.be/euj54cqpGOE>).
This is no attempt to appropriate ownership, just to show how things are even
easier and more concise with pltest.

=head2 Dealing with Files

=over

=item Heads ...

I<People say the back of my head looks really nice -- but I don't see it. :-)>

If you want just I<n>, e.g. 10, lines from the head of each file, use the
optional number argument to B<-p>, along with B<-r> to reset the count.  The
program can be empty, but must be present, unless you're reading from stdin:

    pltest -rp10 '' file*

If you want the head up to a regexp, use the flip-flop operator, starting with
line number 1.  Use the print-if-true B<-P> loop option, again with B<-r> to
reset the count:

    pltest -rP '1../last/' file*

You can combine the two, if you want at most I<n> lines, e.g. 10:

    pltest -rP10 '1../last/' file*

=item ... or Tails?

I<What has a head, a tail, but no legs?  B< >A penny. :-)>

If you want a bigger number of last lines, you need to stuff them in a list;
not really worth it.  But if you want just 1 last line from each file, the
end-of-file B<-e> code (no need to quote, as it has no special characters) can
C<E(cho)> it for you, capitalized so as to not add another newline (yes, Perl
is case sensitive):

    pltest -e Echo '' file*

If you want the tail from a line-number (e.g. 99) or a regexp, use the
flip-flop operator, starting with your regexp and going till each end-of-file:

    pltest -P '99..eof' file*
    pltest -P '/first/..eof' file*

You can even get head and tail (which in programming logic translates to print
if in 1st C<or> 2nd range), if last line of head comes before 1st line of tail
(or actually any number of such disjoint ranges):

    pltest -rP '1../last/ or /first/..eof' file*

=item Remove Trailing Whitespace in Each File

This print-loops (B<-p>) over each file, replacing it (B<-i>) with the
modified output.  Line ends are stripped on reading and added on printing
(B<-l>), because they are also whitespace (C<\s>).  At each end of line,
substitute one or more spaces of any kind (incl. DOS newlines) with nothing:

    pltest -pli 's/\s+$//' file*

=item Tabify/Untabify Each File

This print-loops (B<-p>) over each file, replacing it (B<-i>) with the
modified output.  At beginning of line and after each tab, 8 spaces or less
than 8 followed by a tab are converted to a tab:

    pltest -pi '1 while s/(?:^|\t)\K(?: {1,7}\t| {8})/\t/' file*

To go the other way, subtract the tab-preceding length modulo 8, to get the
number of spaces to replace with:

pod/examples.pod  view on Meta::CPAN

combine|canned-commands/Shell Functions> these variants as Shell functions:

    pltest -o 'piped {
            keydiff $2 if s@.{16} ([\da-f]{8})  (.+)@$1@;
        } "unzip", "-vqq", $_' *.zip

Browsers have a bug of not checking for updated css & javascript.  A common
workaround is to add a hex number to those file names.  In that case use only
the meaningful part of the filename as a key:

    pltest -o 'piped {
            keydiff $2
                if s@.{16} ([\da-f]{8})  (.+?)(?:\.([0-9a-f]{20})(\..[a-z]+))?$@if( $3 ) {
                    $n = "$2.\$x$4"; "$1  \$x=$3"
                } else {
                    $n = $2; $1
                }@e
        } "unzip", "-vqq", $_' *.jar

=item Diff Several Tarballs by Member Name

I<Actually I'm very different.  But I rarely find time for it. --B< >von HorvE<0xe1>th :-)>

This is like the zip example.  Alas, tar gives no checksums, so this is less
reliable.  Exclude directories, by taking only lines not starting with a C<d>.
Each time a wider owner/group or file size was seen, columns shift right.  So
reformat the columns, to not show this as a difference:

    pltest -oB 'echo for @ARGV' 'piped {
            keydiff $4
                if s!^[^d]\S+ \K(.+?) +(\d+) (.{16}) (.+)!Form "%-20s %10d %s", $1, $2, $3!e;
        } "tar", "-tvf", $_' *.tar *.tgz *.txz

Same without the date:

    pltest -o 'piped {
            keydiff $3
                if s!^[^d]\S+ \K(.+?) +(\d+) .{16} (.+)!Form "%-20s %10d", $1, $2!e;
        } "tar", "-tvf", $_' *.tar *.tgz *.txz

Tarballs from the internet have a top directory of F<name-version/>, which
across versions would make every member have a different key.  So exclude the
1st path element from the key by matching C<[^/]+/> before the last paren
group:

    pltest -o 'piped {
            keydiff $4
                if s!^[^d]\S+ \K(.+?) +(\d+) (.{16}) [^/]+/(.+)!Form "%-20s %10d %s", $1, $2, $3!e;
        } "tar", "-tvf", $_' *.tar *.tgz *.txz

Again without the date and owner/group, which can also vary:

    pltest -o 'piped {
           keydiff $2
                if s!^[^d]\S+ \K.+? +(\d+) .{16} [^/]+/(.+)!Form "%10d", $1!e;
        } "tar", "-tvf", $_' *.tar *.tgz *.txz

=item Diff ELF Executables by Loaded Dependencies

You get the idea: you can do this for any command that outputs records with a
unique key.  This one looks at the required libraries and which file they came
from.  For a change, loop with B<-O> and C<$A(RGV)> to avoid the previous
examples' confusion between outer C<$_> which were the cli args, and the inner
one, which were the read lines:

    pltest -O 'piped {
           keydiff if s/^\t(.+\.so.*) => (.*) \(\w+\)/$2/;
        } ldd => $ARGV' exe1 exe2 lib*.so

It's even more useful if you use just the basename as a key, because version
numbers may change:

    pltest -O 'piped {
           keydiff $2 if s/^\t((.+)\.so.* => .*) \(\w+\)/$1/;
        } ldd => $ARGV' exe1 exe2 lib*.so

=back

=head2 Looking at Perl

I<A pig looking at an electric socket:  "Oh no, who put you into that wall?" :)>

=over

=item VERSION of a File

Print the first line (B<-P1>) where the substitution was successful.  To avoid
the hassle of protecting them from (sometimes multiple levels of) Shell
quoting, there are variables for single C<$q(uote)> & double C<$Q(uote)>:

    pltest -P1 's/.+\bVERSION\s*=\s*[v$Quote$quote]{0,2}([0-9.]+).+/$1/' pltest

For multple files, add the filename, and reset (B<-r>) the B<-P> count for each
file:

    pltest -rP1 's/.+\bVERSION\s*=\s*[v$Quote$quote]{0,2}([0-9.]+).+/$ARGV: $1/' *.pm

=item Only POD or non-POD

You can extract either parts of a Perl file, with these commands.  Note that
they don't take the empty line before into account.  If you want that, and
you're sure the files adheres strictly to this convention, use the option
B<-00P> instead (not exactly as desired, the empty line comes after things,
but still, before next thing).  If you want only the 1st POD (e.g. NAME &
SYNOPSIS) use the option B<-P1> or B<-00P1>:

    pltest -P '/^=\w/../^=cut/' file*
    pltest -P 'not /^=\w/../^=cut/' file*

=item Count Perl Code

This makes C<__DATA__> or C<__END__> the last inspected line of (unlike in
C<perl -n>!) each file.  It strips any comment (not quite reliably, also
inside a string).  Then it strips leading whitespace and adds the remaining
length to print-at-end C<$R(ESULT)>:

    pltest -ln 'last if /^__(?:DATA|END)__/;
        s/(?:^|\s+)#.*//s;
        s/^\s+//;
        $RESULT += length' *.pm



( run in 0.959 second using v1.01-cache-2.11-cpan-39bf76dae61 )