NAME
pl - Perl One-Liner Magic Wand
SYNOPSIS
There are always those tasks too menial for dedicated script, but still too cumbersome even with the many neat one-liner options of perl -E
. This small script fills the gap with many bells & whistles: Various one-letter commands & magic variables (with meaningful aliases too) and more nifty loop options take Perl programming to the command line. List::Util
is fully imported. If you pass no program on the command line, starts a simple Perl Shell.
How to e(cho)
values, including from @A(RGV)
, with single $q(uote)
& double $Q(uote)
:
pl 'echo "${quote}Perl$quote", "$Quote@ARGV$Quote"' one liner
pl 'e "${q}Perl$q", "$Q@A$Q"' one liner
> 'Perl' "one liner"
Same for hard-to-print values:
pl 'echo \"Perl", \@ARGV, undef' one liner
pl 'e \"Perl", \@A, undef' one liner
> \'Perl' [
> 'one',
> 'liner'
> ] undef
Loop over args, printing each with line ending. And same, SHOUTING:
pl -opl '' Perl one liner
pl -opl '$_ = uc' Perl one liner
> Perl
> one
> liner
> PERL
> ONE
> LINER
Print up to 3 matching lines, resetting count (and $.
) for each file:
pl -rP3 '/Perl.*one.*liner/' file*
Count hits in magic statistics hash %N(UMBER)
:
pl -n '++$NUMBER{$1} while /(Perl|one|liner)/g' file*
pl -n '++$N{$1} while /(Perl|one|liner)/g' file*
> 2: one
> 7: liner
> 9: Perl
Though they are sometimes slightly, sometimes quite a bit more complicated, most Perl one-liners from the internet work, just by omitting -e
or -E
(pl has only one main program, but you can just as well concatenate the -e
s with ;
). See minor differences for exceptions. There are many varied examples.
DESCRIPTION
Don't believe everything you read on SourceForge^H^H^H the internet! -- Aristotle ;-)
Pl follows Perl's philosophy for one-liners: the one variable solely used in one-liners, @F
, is single-lettered. Because not everyone may like that, Pl has it both ways. Everything is aliased both as a word and as a single letter, including Perl's own @F
& *ARGV
.
Perl one-liners, and hence pl, are by nature bilingual. You must run the command with its options & arguments, typically from Shell. By design, Perl quotes mimic Shell quotes, so here they collide. As Perl also uses Shell meta-characters like $
, the best solution is to protect Perl-code from the Shell with single quotes. That means they can't be used inside. (An ugly way around that is '\''
, which ends a string, blackslashes a quote and starts another. For literal quotes use $q(uote)
.) For quoting use double quotes or q{}
.
DOCUMENTATION
Options
Many of perl's options are also available in pl, sometimes enhanced with extra functionality. And the new options complement what perl offers, specifically oriented towards one liners.
-0[octal]
-
perl: Specify record separator with -n/-p (
\0
, if no argument). -a
-
perl: Autosplit mode with -n/-p (splits
$_
into@F(IELD)
). -bprog
-
Run program before reading a new file in -n/-p.
-Bprog
-
Add program before main program in same scope. So you can use it to initialise
my
variables. Whereas, if you define a my variable in the main program of a -n, -p, -P, -o or -O loop, it's a new variable on each iteration. This doesn't do aBEGIN
block, but this might be changed in a later version if program is wrapped in{}
. -c
-
perl: Check syntax only (runs
BEGIN
andCHECK
blocks). -C[number/list]
-
perl: Enables the listed Unicode features.
--color[=when]
-
Colorize some of the output; when can be
never
,always
, orauto
(the default). -d[:debugger]
-
perl: Run program under debugger.
-D[number/list]
-
perl: Set debugging flags (argument is a bit mask or alphabets).
-eprog
-
Run program after finishing reading a file in -n/-p.
-Eprog
-
Add an
END
block after main-program in same scope. Somy
-vars work as follows: TheEND
block, is a closure of the 1st$inner
variable. Perl warns "Variable "$inner" will not stay shared":pl -OB 'my $outer' -E 'echo $inner, $outer' 'my $inner = $outer = $ARGV' a b c pl -OB 'my $outer' -E 'e $inner, $outer' 'my $inner = $outer = $A' a b c > a c
-f
-
perl: Don't do $sitelib/sitecustomize.pl at startup.
-F/pattern/
-
perl: Provide
split()
pattern for -a switch (//
's are optional). -Idirectory
-
perl: Specify
@INC
/#include
directory (several -I's allowed). -i[extension]
-
perl: Edit
<>
files in place (makes backup if extension supplied). -n
-
perl: Assume
while (<>) { ... }
loop around program. It's a little richer than that: if you uselast
, it closes the current file, leaving you to continue the loop on the next file. -O
-
Assume
for $ARGV (@ARGV) { ... }
loop around main program. In this case -p doesn't imply -n. -o
-
Assume
for(@ARGV) { ... }
loop around main program. In this case -p doesn't imply -n. -p[number]
-
Does
pl -penis
do pussy? It implementscat
. :-*perl++: On each loop
print
(also -o/-O) iteration. If number is given, print at most number times. -P[number]
-
Like -p, but print only if main program evaluates to true, like
grep
. -r
-
Reset
$.
and -p/-P counter for each file. -T
-
perl: Enable tainting checks.
-t
-
perl: Enable tainting warnings.
-U
-
perl: Allow unsafe operations.
-u
-
perl: Dump core after parsing program.
-v
-
perl: Print version, patchlevel and license.
-VVERSION
-
Rerun with given perl version, which is just a string appended to perl.
-W
-
perl: Enable all warnings.
-w
-
perl: Enable many useful warnings.
-X
-
perl: Disable all warnings.
Functions
There are various functions, always also with a one letter alias, which perform little tasks that can be useful in one liners.
benchmark { } [name[, arg...]]
|b { } [name[, arg...]]
-
Benchmark slow code for 10s, display name, looping over args.
Benchmark { } [name[, arg...]]
|B { } [name[, arg...]]
-
Same, but run code 100 times in benchmark, to reduce overhead.
Config [regexp...]
|C [regexp...]
-
Import and return
%Config
, e.g.Config->{sitelib}
, optionally only part matching regexps. Date [arg...][, tz]
|D [arg...][, tz]
-
Why is Halloween Christmas? Because Oct. 31 = Dec. 25. ;-)
Date (from arg [s, us], s{.us}, offset [+-]s{.us}, tz ([+-]0-14{:mm|.ff}). Microseconds should be passed as strings, because floats have implementation-dependent rounding issues. Positive offsets must be passed as strings, because otherwise the
+
gets lost. Returns the date, if called in some context, else echoes it.pl 'Date; $_ = Date -86400, "+3600"; e $_, " -- ", Date "+8:45"' pl 'D; $_ = D -86400, "+3600"; e $_, " -- ", D "+8:45"' > Wed Sep 1 00:25:17.583847 2021 > Tue Aug 31 01:25:17.583923 2021 -- Wed Sep 1 07:10:17.583959 +08:45 2021
echo [arg...]
|e [arg...]
-
Echo prettified args or
$_
with spaces and newline. Prettified means,undef
becomes that string, italic if --color is active. Anything that can be stringified, is. Any other reference goes throughData::Dumper
, which is loaded only if needed.If it is called in scalar context (e.g.
$x = echo ...
) instead return the same as it would echo, in one string (inspired by Shell$(...)
). If it is called in list context (e.g.@l = echo ...
) return each arg prettified individually, with a newline on the last one. Echo [arg...]
|E [arg...]
-
Same, but no newline.
form format, [arg...]
|f format, [arg...]
-
Form(at) and echo prettified args or
$_
with newline. If it is called in scalar or list context (e.g.$x = form ...
) instead return the same as it would echo, in one string. Form format, [arg...]
|F format, [arg...]
-
Same, but no newline.
Isodate [arg...][, tz]
|I [arg...][, tz]
-
Same as
D(ate)
, but uses ISO format.pl 'Isodate; $_ = Isodate 7 * -86400; e $_, " -- ", Isodate "+8.75"' pl 'I; $_ = I 7 * -86400; e $_, " -- ", I "+8.75"' > 2021-09-01T00:25:17.606616 > 2021-08-25T00:25:17.606698 -- 2021-09-01T07:10:17.606730 +08:45
keydiff [key[, value]]
|k [key[, value]]
-
Store value or chomped
$_
in$KEYDIFF{key or $1}[$ARGIND]
. At theEND
for each key (sorted numerically if possible) all values are diffed. Keydiff [number[, value]]
|K [number[, value]]
-
Same, but key is
$FIELD[number]
or$F[0]
. Number [n]
|N [n]
-
Trim
%N(UMBER)
values less than n (default 2) e.g.;-ENumber
or-E 'N 5'
. piped { } cmd[, arg...]
|p { } cmd[, arg...]
-
Open pipe from cmd and loop over it.
Variables
There are various variables, always also with a one letter alias, many of which perform magic tasks at the END
.
*ARGV
|*A
-
perl:
ARGV
,$ARGV
&@ARGV
are all aliased toA
,$A
&@A
. $ARGIND
|$I
-
Index of ARG currently being processed in -o, -n or -p.
@FIELD
|@F
-
perl: This is an alias to loop autosplit variable
@F
. $quote
|$q
-
Predefined to a single quote
'
. There is no magic associated. Perl'sq()
makes it easy to integrate functional quotes under all circumstances. This does the same for literal quotes. $Quote
|$Q
-
Predefined to a double quote
"
. There is no magic associated. Perl'sqq()
makes it easy to integrate functional quotes under all circumstances. This does the same for literal quotes. %KEYDIFF
|%K
-
At END, sort by keys, print keydiff of
$ARGIND
array elements. Filled bykeydiff
. %NUMBER
|%N
-
At END, sort numerically by values.
*RESULT
|*R
-
At END, echo
$RESULT
if defined, then@RESULT
one per line if not empty, then%RESULT
sorted by keys. $ENV{PLDUMP}
-
Since
pl -MO=Deparse
won't show your parts of the program, it can be quite baffling when things go wrong. If you export this before starting pl, you see how your parts get embedded in various bits of generated stuff. If you installperltidy
, it will be used.You will not see the effect of -a, -F or -n as those get wrapped around it by
perl
behind the scenes. Due to interfacing with those options and providing for various option-combinations, the generated code may be too complicated. Expect it to change and be optimized further in the future:PLDUMP=1 \ pl 'say "Hello Perld!"' > sub pl::prog { > $pl::last = 1; > LINE: { > #line 1 "main program" > say "Hello Perld!"; > } continue { > $pl::last = 0; > } > if ( $pl::last || eof ) { > ++$ARGIND; > if ($pl::last) { my $d = $.; close ARGV; $. = $d } > exit if $pl::last == 2; > } > }
COMPATIBILITY
Even if it is rare nowadays, Perl 5.10 is still found out in the wild. Pl tries to accomodate it gracefully, falling back to what works. It has shims for any
, all
, none
, notall
, product
& sum0
. Dumped data-structures may be formatted with a funny margin and h(osts)
will find the less IPv6 resolutions, the older your Perl.
Minor Differences with perl -e
Known minor differences are:
don't
goto LINE
, butnext LINE
is finein a -n loop
last
is per file instead of behaving likeexit
using
pop
, etc. to implicitly modify@A(RGV)
works in -B BEGIN code, but not in your main program (which gets compiled to a function)shenanigans with unbalanced braces won't work
Windows Notes
Work Is Never Done On Windows Systems ;-)
Do yourself a favour and get a real Shell, e.g. from WSL, Cygwin, MSYS, MinGW or git! If you can't avoid command.com or cmd.exe, you will have to first convert all inner quotes to qq
. Then convert the outer single quotes to double quotes:
pl "echo qq{${quote}Perl$quote}, qq{$Quote@ARGV$Quote}" one liner
pl "e qq{${q}Perl$q}, qq{$Q@A$Q}" one liner
> 'Perl' "one liner"
Any help for getting this to work in PowerShell is welcome!
While the old Windows 10 terminal understands ANSI escape sequences, it makes it horribly hard to activate them. So they are off by default, requiring --color to override that choice.
Pl is maintained on SourceForge and also available on meta::cpan.