J
J. Romano
Dear Perl Community,
Over the years of using Perl I discovered some very useful
one-liners that I thought I'd share with the rest of the Perl
community. Some of these one-liners will only work in Unix, so I've
supplied the equivalent DOS one-liner (for Win32 systems) where
possible.
I realize that in many cases there are other ways of doing the same
thing. In some cases, I used one method for a long time before I
discovered a shorter way of doing the same thing. In such cases, I've
included both techniques here.
But if you think you have a better way of doing something I've
listed here, by all means, share it! And if you have any of your own
useful one-liners, feel free to share those as well.
This post is divided into three sections:
* USEFUL ONE-LINERS: One-liners that have been useful
to me in the past
* MORE USEFUL ONE-LINERS: One-liners that I've never
had the need to use, but might
be helpful to someone else
* SHORT FUN PROGRAMS: A couple of cute programs
SECTION 1: USEFUL ONE-LINERS
All of the one-liners in this section have been useful to me at one
time or another in the past.
Everyone should know this one, but just in case they don't, here's how
to find the current date in epoch seconds:
perl -le "print time"
These next few lines explain how to extract the date/time from a value
of epoch seconds (like 1234567890). Many times over the course of
debugging C/C++ programs I've used this technique to find out what
date was being used, making the following line the most useful Perl
one-liner I've ever used:
perl -le "print scalar gmtime 1234567890"
Here's how to find the current date and time:
perl -le "print scalar gmtime time"
Here's how to find the so-called "beginning of time":
perl -le "print scalar gmtime 0"
Here's how to find the date of the one-billionth second after time 0:
perl -le "print scalar gmtime 1e9"
This gives the date of the fabled "end of time":
perl -le "print scalar gmtime 0x7f_ff_ff_ff"
Many times I've wanted to convert a hexadecimal number (like 0xface)
into decimal:
perl -le "print 0xface"
And other times I needed to convert a decimal number (like 255) into
hexadecimal:
# Unix:
perl -e 'printf "0x%x\n", 255'
# DOS:
perl -e "printf qq/0x%x\n/, 255"
I do a lot of work with binary files. Sometimes I need to find the
value of a specific bit in a binary file. Here is how to convert a
binary file into its binary 0s and 1s:
# Unix:
perl -l -0777 -ne 'print unpack("B*", $_)' binary_file
# DOS (using ActiveState Perl 5.8 or later):
perl -l -Mopen=IO,:raw -0777 -ne "print unpack('B*', $_)" binary_file
(Note: Replace the 'B*' packstring with 'H*' to see the hexadecimal
equivalent.)
Here's a handy one for determining if your machine is little-endian or
big-endian:
perl -le "print((ord pack 's', 1) ? 'little' : 'big', '-endian')"
Note: "perldoc -f pack" describes another way for determining
endian-ness by using $Config{byteorder}. Here is a solution that uses
that method (note: I use '@' instead of '$' so that this one-liner
will run under both DOS and Unix):
perl -MConfig -le "print @Config{byteorder}"
The string "1234" or "12345678" signifies little-endian; "4321" or
"87654321" signifies big-endian. If you get something out of order,
it means that your machine is netiher big- nor little-endian!
Use this to find out the size of an integer (in bytes):
perl -le "print length pack 'i', 0"
Note: "perldoc -f pack" describes another way for determining this
using $Config{intsize}. Here is a solution that uses that method
(note: I use '@' instead of '$' so that this one-liner will run under
both DOS and Unix):
perl -MConfig -le "print @Config{intsize}"
Here is a small Perl interactive interpreter:
# Unix:
perl -ne 'eval; print "$@\n> "'
# DOS:
perl -ne "eval; print qq/$@\n> /"
After typing out this one-liner, hit ENTER twice to see the
interactive interpreter prompt. Type "exit" to quit the interpreter.
Note: Many readers know that "perl -de 1" will do just about the same
thing, and it's more flexible with more advantages (and quicker to
type). That's true, but remember that to exit "perl -de 1" you must
type "q", not "exit".
Use this to count number of characters in a string (not counting the
newline):
perl -lne "chomp; print tr///c"
This removes duplicate entries in the PATH environment variable:
(Note: this only works on Unix)
exec perl -e'$ENV{PATH}=join":",grep{not$seen{$_}++}split/:/,$ENV{PATH};exec$ENV{SHELL}'
Note that this spawns a child shell (and so has whatever advantages
and disadvantages that go with it). This one-liner is meant to be run
from an interactive shell and will NOT work from inside another
script. Therefore, this may not be suitable for all purposes.
SECTION 2: MORE USEFUL ONE-LINERS
The one-liners in this section might be useful to someone, but I can't
say I've ever really needed them very badly myself.
Convert tabs into spaces (assuming a tabstop is 8 spaces):
# Unix:
perl -MText::Tabs -ne '$tabstop=8; print expand($_)'
# DOS:
perl -MText::Tabs -ne "$tabstop=8; print expand($_)"
Sort a list of items (such as songs, foods, or books) in order of
preference:
# Unix:
perl -e 'print sort{print "1. ${a}2. ${b}Preference: ";<>*2-3}<>'
# DOS:
perl -e "print sort{print qq/1. ${a}2. ${b}Preference: /;<>*2-3}<>"
To try this out, run it and type:
chocolate
brussel sprouts
bread
and hit CTRL-D (or CTRL-Z and ENTER if you're using DOS). You will be
asked a series of questions asking what you prefer. (Hint: to say
that you like both the same, you can type a value of "1.5".)
This sort works provided that you are consistent (no changing your
mind halfway through the sort) and that you don't have any circular
preferences (an example of a circular preference is: I like book A
more than book B, book B more than book C, and book C more than book
A).
SECTION 3: SHORT FUN PROGRAMS
Here are some fun short programs and one-liners that do nothing
particularly useful, but are just for fun.
Here's a program that I like to call the "Spooky Writer":
# Unix:
perl -e'$|=1;for(split//,join"",<>){print;select(undef,undef,undef,rand(.5))}'
# DOS:
perl -e"$|=1;for(split//,join'',<>){print;select(undef,undef,undef,rand(.5))}"
Try and figure out what it does. If you have trouble figuring it out,
try running the one-liner, and type a few lines from your favorite
poem. Then hit CTRL-D (or CTRL-Z and ENTER if you're using DOS), and
watch what happens! Spooky, eh? You can run the JAPH at the bottom
of this post to see a variation of this one-liner.
If you're still having trouble figuring this code out, try the
following short script which does the same thing but is easier to
understand:
#!/usr/bin/perl -w
use strict;
# Set the maximum wait in seconds.
# The average wait will be half that:
my $maxWait = 0.50; # in seconds
$| = 1; # autoflush
# Get all input:
my @inputLines = <>;
my $input = join('', @inputLines);
my @charList = split(//, $input);
# @charList now holds an array of characters of all the input
# Loop through each character, printing the character and
# then waiting for a short time:
foreach my $char (@charList)
{
print $char;
# Pause for a short (and random) time:
my $pauseTime = rand($maxWait);
select(undef, undef, undef, $pauseTime);
}
__END__
And finally, for the last program I present a self-replicating
program! This entire program is six lines long:
#!/usr/bin/perl
print((@d=<DATA>)x2);
__END__
#!/usr/bin/perl
print((@d=<DATA>)x2);
__END__
A self-replicating program is a program that, when run, produces its
code as output. These programs are tricky to write, because if one
character is changed, usually one or more other characters have to be
changed as well.
In perl, you can run a self-replicating program like this:
perl repeat.pl | perl | perl | perl | perl
and no matter how many "| perl" instances you write, the output will
still be the same!
Unfortunately, I couldn't come up with a self-replicating Perl
one-liner, but if someone knows of one, I'd like to see it!
If you think the above six-line program is difficult to understand,
here's essentially the same program, but easier to follow (note: the
entire program is 12 lines long):
#!/usr/bin/perl -w
use strict;
my @d = <DATA>; # get half of this script
print @d; # print the top half of this script
print @d; # print the bottom half of this script
__END__
#!/usr/bin/perl -w
use strict;
my @d = <DATA>; # get half of this script
print @d; # print the top half of this script
print @d; # print the bottom half of this script
__END__
Well, that's it for useful one-liners and small Perl programs. I
hope you enjoyed them. If you have any one-liners that have been
useful to you, feel free to share them. I'd love to see them.
Happy Perling,
Jean-Luc Romano
--
# JAPH (for Unix):
perl -e'$|=1;select($J,$L,$R,rand.7*print)for split//,"Just another
Perl hacker\n"'
# JAPH (for DOS):
perl -e"$|=1;select($J,$L,$R,rand.7*print)for split//,qq/Just another
Perl hacker\n/"
Over the years of using Perl I discovered some very useful
one-liners that I thought I'd share with the rest of the Perl
community. Some of these one-liners will only work in Unix, so I've
supplied the equivalent DOS one-liner (for Win32 systems) where
possible.
I realize that in many cases there are other ways of doing the same
thing. In some cases, I used one method for a long time before I
discovered a shorter way of doing the same thing. In such cases, I've
included both techniques here.
But if you think you have a better way of doing something I've
listed here, by all means, share it! And if you have any of your own
useful one-liners, feel free to share those as well.
This post is divided into three sections:
* USEFUL ONE-LINERS: One-liners that have been useful
to me in the past
* MORE USEFUL ONE-LINERS: One-liners that I've never
had the need to use, but might
be helpful to someone else
* SHORT FUN PROGRAMS: A couple of cute programs
SECTION 1: USEFUL ONE-LINERS
All of the one-liners in this section have been useful to me at one
time or another in the past.
Everyone should know this one, but just in case they don't, here's how
to find the current date in epoch seconds:
perl -le "print time"
These next few lines explain how to extract the date/time from a value
of epoch seconds (like 1234567890). Many times over the course of
debugging C/C++ programs I've used this technique to find out what
date was being used, making the following line the most useful Perl
one-liner I've ever used:
perl -le "print scalar gmtime 1234567890"
Here's how to find the current date and time:
perl -le "print scalar gmtime time"
Here's how to find the so-called "beginning of time":
perl -le "print scalar gmtime 0"
Here's how to find the date of the one-billionth second after time 0:
perl -le "print scalar gmtime 1e9"
This gives the date of the fabled "end of time":
perl -le "print scalar gmtime 0x7f_ff_ff_ff"
Many times I've wanted to convert a hexadecimal number (like 0xface)
into decimal:
perl -le "print 0xface"
And other times I needed to convert a decimal number (like 255) into
hexadecimal:
# Unix:
perl -e 'printf "0x%x\n", 255'
# DOS:
perl -e "printf qq/0x%x\n/, 255"
I do a lot of work with binary files. Sometimes I need to find the
value of a specific bit in a binary file. Here is how to convert a
binary file into its binary 0s and 1s:
# Unix:
perl -l -0777 -ne 'print unpack("B*", $_)' binary_file
# DOS (using ActiveState Perl 5.8 or later):
perl -l -Mopen=IO,:raw -0777 -ne "print unpack('B*', $_)" binary_file
(Note: Replace the 'B*' packstring with 'H*' to see the hexadecimal
equivalent.)
Here's a handy one for determining if your machine is little-endian or
big-endian:
perl -le "print((ord pack 's', 1) ? 'little' : 'big', '-endian')"
Note: "perldoc -f pack" describes another way for determining
endian-ness by using $Config{byteorder}. Here is a solution that uses
that method (note: I use '@' instead of '$' so that this one-liner
will run under both DOS and Unix):
perl -MConfig -le "print @Config{byteorder}"
The string "1234" or "12345678" signifies little-endian; "4321" or
"87654321" signifies big-endian. If you get something out of order,
it means that your machine is netiher big- nor little-endian!
Use this to find out the size of an integer (in bytes):
perl -le "print length pack 'i', 0"
Note: "perldoc -f pack" describes another way for determining this
using $Config{intsize}. Here is a solution that uses that method
(note: I use '@' instead of '$' so that this one-liner will run under
both DOS and Unix):
perl -MConfig -le "print @Config{intsize}"
Here is a small Perl interactive interpreter:
# Unix:
perl -ne 'eval; print "$@\n> "'
# DOS:
perl -ne "eval; print qq/$@\n> /"
After typing out this one-liner, hit ENTER twice to see the
interactive interpreter prompt. Type "exit" to quit the interpreter.
Note: Many readers know that "perl -de 1" will do just about the same
thing, and it's more flexible with more advantages (and quicker to
type). That's true, but remember that to exit "perl -de 1" you must
type "q", not "exit".
Use this to count number of characters in a string (not counting the
newline):
perl -lne "chomp; print tr///c"
This removes duplicate entries in the PATH environment variable:
(Note: this only works on Unix)
exec perl -e'$ENV{PATH}=join":",grep{not$seen{$_}++}split/:/,$ENV{PATH};exec$ENV{SHELL}'
Note that this spawns a child shell (and so has whatever advantages
and disadvantages that go with it). This one-liner is meant to be run
from an interactive shell and will NOT work from inside another
script. Therefore, this may not be suitable for all purposes.
SECTION 2: MORE USEFUL ONE-LINERS
The one-liners in this section might be useful to someone, but I can't
say I've ever really needed them very badly myself.
Convert tabs into spaces (assuming a tabstop is 8 spaces):
# Unix:
perl -MText::Tabs -ne '$tabstop=8; print expand($_)'
# DOS:
perl -MText::Tabs -ne "$tabstop=8; print expand($_)"
Sort a list of items (such as songs, foods, or books) in order of
preference:
# Unix:
perl -e 'print sort{print "1. ${a}2. ${b}Preference: ";<>*2-3}<>'
# DOS:
perl -e "print sort{print qq/1. ${a}2. ${b}Preference: /;<>*2-3}<>"
To try this out, run it and type:
chocolate
brussel sprouts
bread
and hit CTRL-D (or CTRL-Z and ENTER if you're using DOS). You will be
asked a series of questions asking what you prefer. (Hint: to say
that you like both the same, you can type a value of "1.5".)
This sort works provided that you are consistent (no changing your
mind halfway through the sort) and that you don't have any circular
preferences (an example of a circular preference is: I like book A
more than book B, book B more than book C, and book C more than book
A).
SECTION 3: SHORT FUN PROGRAMS
Here are some fun short programs and one-liners that do nothing
particularly useful, but are just for fun.
Here's a program that I like to call the "Spooky Writer":
# Unix:
perl -e'$|=1;for(split//,join"",<>){print;select(undef,undef,undef,rand(.5))}'
# DOS:
perl -e"$|=1;for(split//,join'',<>){print;select(undef,undef,undef,rand(.5))}"
Try and figure out what it does. If you have trouble figuring it out,
try running the one-liner, and type a few lines from your favorite
poem. Then hit CTRL-D (or CTRL-Z and ENTER if you're using DOS), and
watch what happens! Spooky, eh? You can run the JAPH at the bottom
of this post to see a variation of this one-liner.
If you're still having trouble figuring this code out, try the
following short script which does the same thing but is easier to
understand:
#!/usr/bin/perl -w
use strict;
# Set the maximum wait in seconds.
# The average wait will be half that:
my $maxWait = 0.50; # in seconds
$| = 1; # autoflush
# Get all input:
my @inputLines = <>;
my $input = join('', @inputLines);
my @charList = split(//, $input);
# @charList now holds an array of characters of all the input
# Loop through each character, printing the character and
# then waiting for a short time:
foreach my $char (@charList)
{
print $char;
# Pause for a short (and random) time:
my $pauseTime = rand($maxWait);
select(undef, undef, undef, $pauseTime);
}
__END__
And finally, for the last program I present a self-replicating
program! This entire program is six lines long:
#!/usr/bin/perl
print((@d=<DATA>)x2);
__END__
#!/usr/bin/perl
print((@d=<DATA>)x2);
__END__
A self-replicating program is a program that, when run, produces its
code as output. These programs are tricky to write, because if one
character is changed, usually one or more other characters have to be
changed as well.
In perl, you can run a self-replicating program like this:
perl repeat.pl | perl | perl | perl | perl
and no matter how many "| perl" instances you write, the output will
still be the same!
Unfortunately, I couldn't come up with a self-replicating Perl
one-liner, but if someone knows of one, I'd like to see it!
If you think the above six-line program is difficult to understand,
here's essentially the same program, but easier to follow (note: the
entire program is 12 lines long):
#!/usr/bin/perl -w
use strict;
my @d = <DATA>; # get half of this script
print @d; # print the top half of this script
print @d; # print the bottom half of this script
__END__
#!/usr/bin/perl -w
use strict;
my @d = <DATA>; # get half of this script
print @d; # print the top half of this script
print @d; # print the bottom half of this script
__END__
Well, that's it for useful one-liners and small Perl programs. I
hope you enjoyed them. If you have any one-liners that have been
useful to you, feel free to share them. I'd love to see them.
Happy Perling,
Jean-Luc Romano
--
# JAPH (for Unix):
perl -e'$|=1;select($J,$L,$R,rand.7*print)for split//,"Just another
Perl hacker\n"'
# JAPH (for DOS):
perl -e"$|=1;select($J,$L,$R,rand.7*print)for split//,qq/Just another
Perl hacker\n/"