This is the fourth part of a nine-part article on Perl one-liners. In this part I will create various one-liners for string and array creation. See part one for introduction of the series.
Perl one-liners is my attempt to create "perl1line.txt" that is similar to "awk1line.txt" and "sed1line.txt" that have been so popular among Awk and Sed programmers.
The article on Perl one-liners will consist of nine parts:
- Part I: File spacing.
- Part II: Line numbering.
- Part III: Calculations.
- Part IV: String creation and array creation (this part).
- Part V: Text conversion and substitution.
- Part VI: Selective printing and deleting of certain lines.
- Part VII: Handy regular expressions.
- Part VIII: Release of perl1line.txt.
- Part IX: Release of Perl One-Liners e-book.
I decided that there will be two new parts in this series. The most powerful feature in Perl is its regular expressions, therefore I will write a part on "Handy Perl regular expressions." I also decided to publish an e-book after I am done with the series, so that will be the last part of this series. Subscribe to my blog to know when that happens!
Awesome news: I have written an e-book based on this article series. Check it out:
I also updated the previous part on calculations with 14 new one-liners on finding values of constants pi and e, doing date calculations, finding factorial, greatest common divisor, least common multiple, generating random numbers, generating permutations, finding power sets and doing some IP address conversions.
Here are today's one-liners:
String Creation and Array Creation
49. Generate and print the alphabet.
perl -le 'print a..z'
This one-liner prints all the letters from a to z as abcdefghijklmnopqrstuvwxyz
. The letters are generated by the range operator ..
. The range operator, when used in the list context (which is forced here by print
) on strings, uses the magical auto-increment algorithm that advances the string to the next character. So in this one-liner the auto-increment algorithm on the range a..z
produces all the letters from a to z.
I really golfed this one-liner. If you used strict
it would not work because of barewords a
and z
. Semantically more correct version is this:
perl -le 'print ("a".."z")'
Remember that the range operator ..
produced a list of values. If you want, you may print them comma separated by setting the $,
special variable:
perl -le '$, = ","; print ("a".."z")'
There are many more special variables. Take a look at my special variable cheat sheet for a complete listing.
Syntactically more appealing is to use join to separate the list with a comma:
perl -le 'print join ",", ("a".."z")'
Here the list a..z
gets joined by a comma before printing.
50. Generate and print all the strings from "a" to "zz".
perl -le 'print ("a".."zz")'
Here the range operator ..
is used again. This time it does not stop at "z" as in the previous one-liner, but advances z by one-character producing "aa", then it keeps going, producing "ab", "ac", ..., until it hits "az". At this point it advances the string to "ba", continues with "bb", "bc", ..., until it reaches "zz".
Similarly, you may generate all strings from "aa" to "zz" by:
perl -le 'print "aa".."zz"'
Here it goes like "aa", "ab", ..., "az", "ba", "bb", ..., "bz", "ca", ... "zz".
51. Create a hex lookup table.
@hex = (0..9, "a".."f")
Here the array code>@hex</code gets filled with values 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
and letters a, b, c, d, e, f
.
You may use this array to convert a number (in variable $num
) from decimal to hex using base conversion formula:
perl -le '$num = 255; @hex = (0..9, "a".."f"); while ($num) { $s = $hex[($num%16)&15].$s; $num = int $num/16 } print $s'
Surely, much easier way to convert a number to hex is just using the printf
function (or sprintf
function) with %x
format specifier. (The example above just illustrates a use of a hex lookup table that we created by using the range operator.)
perl -le '$hex = sprintf("%x", 255); print $hex'
(See my Perl printf and sprintf format cheat sheet for all the format specifiers.)
To convert the number back from hex to dec use the hex
function:
perl -le '$num = "ff"; print hex $num'
The hex
function takes a hex string (beginning with or without "0x") and converts it to decimal.
52. Generate a random 8 character password.
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
Here the map function executes ("a".."z")[rand 26]
code 8 times (because it iterates over the dummy range 1..8
). In each iteration the code chooses a random letter from the alphabet. When map
is done iterating, it returns the generated list of characters and print
function prints it out by concatenating all the characters together.
If you also want to include numbers in the password, add 0..9
to the list of characters to choose from and change 26
to 36
as there are 36 different characters to choose from:
perl -le 'print map { ("a".."z", 0..9)[rand 36] } 1..8'
If you need a longer password, change 1..8
to 1..20
to generate a 20 character long password.
53. Create a string of specific length.
perl -le 'print "a"x50'
Operator x
is the repetition operator. This one-liner creates a string of 50 letters "a" and prints it.
If the repetition operator is used in list context, it creates a list (instead of scalar) with the given elements repeated:
perl -le '@list = (1,2)x20; print "@list"'
This one liner creates a list of twenty repetitions of (1, 2) (it looks like (1, 2, 1, 2, 1, 2, ...)).
54. Create an array from a string.
@months = split ' ', "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
Here the code>@months</code gets filled with values from the string containing month names. As each month name is separated by a space, the split
function splits them and puts them in code>@months</code. This way $months[0]
contains "Jan", $months[1]
contains "Feb", ..., and $months[11]
contains "Dec".
Another way to do the same is by using qw//
operator:
@months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/
The qw//
operator takes a space separated string and creates an array with each word being an array element.
55. Create a string from an array.
@stuff = ("hello", 0..9, "world"); $string = join '-', @stuff
Here the values in array code>@stuff</code get turned in a string $string
that has them separated by a hyphen. Turning an array in a string was done by the join
function that takes a separator and a list, and concatenates the items in the list in a single string, separated by the separator.
56. Find the numeric values for characters in the string.
perl -le 'print join ", ", map { ord } split //, "hello world"'
This one-liner takes the string "hello world", splits it into a list of characters by split //, "hello world"
, then it map
s the ord
function onto each of the characters, which returns the numeric, native 8-bit encoding (like ASCII or EBCDIC) of the character. Finally all the numeric values get joined together by a comma and get printed out.
Another way to do the same is use the unpack
function and specify C
as the unpacking template (C means unsigned character and means as many characters there are):
perl -le 'print join ", ", unpack("C*", "hello world")'
57. Convert a list of numeric ASCII values into a string.
perl -le '@ascii = (99, 111, 100, 105, 110, 103); print pack("C*", @ascii)'
Just as we unpacked a string into a list of values with the C*
template in the one-liner above, we can pack them back into a string.
Another way to do the same is use the chr
function that takes the code point value and returns the corresponding character:
perl -le '@ascii = (99, 111, 100, 105, 110, 103); print map { chr } @ascii'
Similar to one-liner #55 above, function chr
gets mapped onto each value in the code>@ascii</code producing the characters.
58. Generate an array with odd numbers from 1 to 100.
perl -le '@odd = grep {$_ % 2 == 1} 1..100; print "@odd"'
This one-liner generates an array of odd numbers from 1 to 99 (as 1, 3, 5, 7, 9, 11, ..., 99). It uses the grep
function that evaluates the given code $_ % 2 == 1
for each element in the given list 1..100
and returns only the elements that had the code evaluate to true. In this case the code tests if the reminder of the number is 1. If it is, the number is odd and it has to be put in the code>@odd</code array.
Another way to write is by remembering that odd numbers have the low-bit set and testing this fact:
perl -le '@odd = grep { $_ & 1 } 1..100; print "@odd"'
Expression $_ & 1
isolates the low-bit, and grep selects only the numbers with low-bit set (odd numbers).
See my explanation of bit-hacks for full explanation and other related bit-hacks.
59. Generate an array with even numbers from 1 to 100.
perl -le '@even = grep {$_ % 2 == 0} 1..100; print "@even"'
This is almost the same as the previous one-liner, except the condition grep
tests for is "is the number even (reminder dividing by 2 is zero)?"
60. Find the length of the string.
perl -le 'print length "one-liners are great"'
Just for completeness, the length
subroutine finds the length of the string.
61. Find the number of elements in an array.
perl -le '@array = ("a".."z"); print scalar @array'
Evaluating an array in a scalar context returns the number of elements in it.
Another way to do the same is by adding one to the last index of the array:
perl -le '@array = ("a".."z"); print $#array + 1'
Here $#array
returns the last index in array code>@array</code. Since it's a number one less than the number of elements, we add 1 to the result to find the total number of elements in the array.
Perl one-liners explained e-book
I've now written the "Perl One-Liners Explained" e-book based on this article series. I went through all the one-liners, improved explanations, fixed mistakes and typos, added a bunch of new one-liners, added an introduction to Perl one-liners and a new chapter on Perl's special variables. Please take a look:
Have Fun and until next time
Have fun with these one-liners for now. The next part is going to be about text conversion and substitution. It's almost done and will publish it in a couple of days. Check back soon.