Archive

Posts Tagged ‘perl’

Perl Hash Slices

May 22nd, 2014 subogero Comments off

Perl always does what you want, except if you want consistency.

I remember those “Wouldn’t it be great?” moments throughout my Perl hacking years. The answer was invariably “Yes, you can”.

Wouldn’t it be great if you could interpolate variables into regular expressions? Yes. you can.
Wouldn’t it be great if you could address a hash with a subset of keys and get a subset of values? Yes, you can.

Which, in turn, brings me to hash slices and a few related tricks.

Slicing Hashrefs

This is how you slice a hash, building an array of values from an array of corresponding keys. Pythonistas may now notice the beautiful simplicity compared to their silly list comprehensions…

%hash = (one => 1, two => 2, three => 3);
@one_three = @hash{'one', 'three'};

But how to slice a hashref?

$hashref = {one => 1, two => 2, three => 3};
@one_three = @{$hashref}{'one', 'three'};

The rule is that if you have a $hashref instead of a %hash, you can do everything the same way, just replace the bare sigil-less name of the hash with {$hashref}. Pythonistas are at this moment enlightened about the usefulness of sigils.

Merging Hashes

Hash slices can be lvalues too, so you can assign an array of values to an array of keys.

%numbers = (one => 1, two => 2);
%more = (three => 3, four => 4);
@numbers{keys %more} = values %more;

Note the @ sigil in front of all hash slices. They are arrays!

Categories: Uncategorized Tags: , , , ,

I am a Webmaster

September 27th, 2010 subogero Comments off

It happened that I had to put together a few html pages containing important info about a certain project at the company. Originally I stored them on a Samba share on the official Windows file-server. I turned out to be terrible. For instance Firefox needs FIVE slashes after the protocol-id in the URL:

file://///server/share/page.html

IE needs two, Chrome needs four. First step in the downward spiral: I need the http protocol, in other words a webserver. So I installed Cygwin’s lighttpd on our constantly running desktop box. Then moved the html files to “/srv/www/htdocs/site/”. First step done.

Next step: it’s very cumbersome to change the navigation links, whenever a new page is added. Time to automatize. Tools: SSI (server side includes) and CGI scripts in Perl.

Then, what about setting up a few mailing lists. No archiving, just free subscribing and sending mail via “mailto:” links. One day job in Perl.

Later SSI turned out to be a bad choice as you need an absolute path to your CGI script. Difficult if you want a test-site. So I rewrote the entire site that all links actually refer to the same CGI script which loads the required page, adding dynamic navigation.

The trickiest and nicest part is managing the website with git. On the server I set up a git repo in my home folder, with a detached worktree in “/srv/www/htdocs/site”:

server ~$ mkdir site.git && cd site.git
server ~/site.git$ git --bare init
server ~/site.git$ git config core.worktree '/srv/www/htdocs/site'
server ~/site.git$ git config receive.denycurrentbranch false

Additionally, we need a hook routine which checks out anything to the website whenever you push it into this repo:

server ~/site.git$ mv hooks/post-receive.sample hooks/post-receive
server ~/site.git$ mcedit hooks/post-receive
# checkout the received branch to the website
read OLD NEW REF
git checkout -f $RE

On my own machine, I also have a git repo to manage the site. To allow easy server-updates, I did this:

mybox ~/site$ git remote add web ssh://server/~/site.git
mybox ~/site$ git push web master

Finally, one wants a test-site. Lighty endeavours to give satisfaction, so simply enable module mod_userdir in /etc/lighttpd/lighttpd.conf, and each user’s public_html folder becomes his own website. The two lines below now refer to the same folder:

/home/foo/public_html/
http://server/~foo/

Let’s create a non-bare repo here and configure it to receive and automatically check out pushed commits:

server ~/public_html$ mkdir site && cd site
server ~/public_html/site$ git init
server ~/public_html/site$ git config receive.denycurrentbranch false

I applied the same post-receive hook as with the official website’s repo. But it refused to check out the pushed commits. After a considerable amount of cursing it turns out the bloody git runs the hooks in the “.git” folder. I discovered this when I found all my html files there. So the post-receive hook should look like this in a non bare repo:

#!/bin/sh
unset GIT_DIR
unset GIT_WORK_TREE
cd ..
read OLD NEW REF
REF=`echo $REF | sed 's:refs/..*/::'` # branch instead of detached head
git checkout -f $REF

On my box I added an other remote to allow pushing to the test site:

mybox ~/site$ git remote add test ssh://server/~/public_html/site
mybox ~/site$ git push test master

I even applied a post-commit hook on the local machine which pushes master-commits to the official site and branch-commits to the test site.

Perl 3

April 6th, 2010 subogero Comments off

The Camel Book has arrived. It does not reach P. G. Wodehouse’s joke density (3 per word), but it’s close. And it’s 1000 pages. So Larry may have beaten Pelham Grenville in the overall joke count.

Perl 2

April 2nd, 2010 subogero Comments off

I’ve ordered the Camel Book. Can’t wait…

Categories: Uncategorized Tags: , ,

Perl

March 27th, 2010 subogero Comments off

I love Perl. The beautiful friendship started blossoming recently. I remember a few years ago, before I got infected with Unix, I was always scared to death when confronted with Perl. But after half a year of meddling with Bash, GNU coreutils and regular expressions, I happened to look into an occasional Camel-smelling script and, much to my surprise, I was literally shocked by its beauty. Let me list my personal highlights.

Perl is like human languages.

open(FILE, "< $filename") or die "$filename could not be opened for reading.";

In Perl, there are many ways to express yourself to stress different things, like in human languages. Not like in German.

if ($foo) { print "Foo!"; }
print "Foo!" if ($foo);
print "Foo!" unless (!$foo);

Perl is very terse, like good slang.

Ever heard of Perl Golf?

Perl comes with batteries included.

With everything from Bash and coreutils, without using any extra modules. In the little Hungarian calendar below, I open a filehandle for a pipe from another program, I use the command line arguments, I do string substitutions.

#!/usr/bin/perl
open CAL, "cal -m @ARGV |";
while (<CAL>) {
  s/January/ Január/;
  # translations for other months and days ...
  print;
}
close CAL;

I forget, where did I hear this “batteries included” last time?

Default variable $_, especially when it’s not even written. Just like ogc (or vice versa).

Look at the code above. Guess what the s/// substitution is working on? Guess what is printed? Exactly. The hidden $_ variable, the result of the previous operation.

Variable substitution within regular expressions.

In my first ever Perl-script I came across some substitution problem where a part of the pattern to change was stored in a variable. I thought: How nice it would be to be able to put the variable into the regexp. I googled it. Of course it works.

$foo =~ s/(^.* )$variable$/$1$bar/;

And don’t tell me it’s unreadable…

Perl is available for Windows.

At the slightly brain-damaged company I work for, I can write small programs for slightly brain-damaged users. They don’t have to install Cygwin to run them, but Perl gives me the full arsenal of Unix.

The Perl style guide.

Compactness. Readability. No bullshit.

The Camel book.

I keep laughing out loud reading it.

Larry Wall is a Bible guy.

Remember, Perl comes from a linguist who originally wanted to translate the Bible into exotic languages.

Larry Wall is always right.

Even when he is not.

Categories: Uncategorized Tags: , ,