October 11, 2008

Processing all files in a directory - Perl

From this week's Perl course:

opendir(DH, ".");
while ($igot = readdir(DH)) {
  next if ($igot =~ /^\.{1,2}$/);
  print "igot $igot\n";
}

You'll notice that I have used a regular expression to check for files called dot and dot-dot, which are the current and parent directory, as I typically would NOT want to process each of them in my loop.

Other alternatives ... this is Perl so "There is more than one way" ... include:

@files = glob("*");

@files = <*>

@files = `ls`

but although each of these is shorter, they are not recommended for heavy directory traversal applications - in each case, they return you a sorted list of names and that sorting can be useful for a single directory, but wasteful in a heavier application that's going through a large number of directories.

Once you are traversing a directory, you can do all sorts of things - use operators such as -d to find out what is a subdirectory, and -s to find the size of individual contents, for example.

If you want to find the biggest file in or below a directory (perhaps you're running out of disc space?), we have a sample program here from our Perl for larger projects course.

Posted by gje at 07:25 AM | Comments (0)

More about Graham Ellis of Well House Consultants
Useful link: Perl training

Text formating for HTML, with PHP

Do you want "normal" text that's formatted in a fixed width font, with white spaces and tabs and new line characters to have a similar appearance on a browser? The default answer of you generate a page of HTML is "tough luck", as text defaults to a variable width font, lines are squished together with mulriple spaced becoming single spaces, and even new lines are treated as just white space.

You want:

/dev/disk0s3    117089712 83067248  33766464    72%    /
devfs 106 106 0 100% /dev
fdesc 1 1 0 100% /dev
map -hosts 0 0 0 100% /net
map auto_home 0 0 0 100% /home
/dev/disk1 3674142 3674142 0 100% /Vol/MOS

but you get:

/dev/disk0s3 117089712 83067248 33766464 72% / devfs 106 106 0 100% /dev fdesc 1 1 0 100% /dev map -hosts 0 0 0 100% /net map auto_home 0 0 0 100% /home /dev/disk1 3674142 3674142 0 100% /Vol/MOS

How can you achieve the effect you desire? There are or have been a number of options:

a) The <PRE> to </PRE> tag pair - though even within there you need to be careful of & and < characters.

b) white-space: pre; within your CSS - but there are issues with how some versions of Internet Explorer handle that attribute

c) Specify Content-Type: text/plain in your headers, but that will turn the whole document into pure text - rather like letting the tail wag the dog

d) Setting the columns of data you see in the example above into columns of a table to achieve a display which is not identical, but has a similar readability

e) Using a fixed width font such as courier, converting spaces to &nbsp; special characters, and converting new lines into <br /> tags.

Take your choice - there are times that each option is a good one. If you're coding in PHP, then there's a function in the language - nl2br - that converts new lines to line breaks, and you could also use preg_replace to convert spaces into &nbsp; - s

Here's a sample PHP program that uses nl2br - and I have also taken the opportunity to illustrate a "here document" which allows me to add a multiline block of text within my PHP. The <<< syntax is oft overlooked ....

<?php
 
$line = "The Pie Shop\n25 High Street\nSalisbury\nWilts\n\n";
print ($line);
print (nl2br($line));
 
$haircut = <<<BALD
I used to have %colour% hair, then I went
grey and then I became hairless. With %colour%
hair, they used to call me "bushy". With grey,
they thought I was a whizz or wizzard, and now
I'm called Coot.
 
BALD;
 
$output = preg_replace("/%colour%/","ginger",$haircut);
 
print (nl2br($output));

When I run this from the command line, I get:

The Pie Shop
25 High Street
Salisbury
Wilts
 
The Pie Shop<br />
25 High Street<br />
Salisbury<br />
Wilts<br />
<br />
I used to have ginger hair, then I went<br />
grey and then I became hairless. With ginger<br />
hair, they used to call me "bushy". With grey,<br />
they thought I was a whizz or wizzard, and now<br />
I'm called Coot.<br />

and if I display it part of an HTML stream, it looks like this:

The Pie Shop 25 High Street Salisbury Wilts The Pie Shop
25 High Street
Salisbury
Wilts
 
I used to have ginger hair, then I went
grey and then I became hairless. With ginger
hair, they used to call me "bushy". With grey,
they thought I was a whizz or wizzard, and now
I'm called Coot.

See also ... offsite link - a further desctiption of the HTML and CSS options, and our PHP Techniques course and resources

Posted by gje at 06:40 AM | Comments (0)
Useful link: PHP training

October 10, 2008

Caen Hill and Olivers Castle

It's October - but yesterday was a lovely evening and after the course finished for the day, Mark (one of our delegates) and I went out and spent a brief period looking at some of the local countryside. This is canal side at Caen Hill - about five miles from us.

A handful of miles further on, on the edge of the Downs, is Oliver's Castle - named after Oliver Cromwell, who fought here in the battle of Roundway in the English Civil War. There are boards on the site telling you all about it, and it's a nature reserve too where you can see the local flora and fauna.

The days are drawing in, and there's not much time to take photos before dusk at this time of year - soon, we were onto sunset shots - here with the gaunt trees of Oliver's Castle

And a final shot as a heron comes in to land for the night at Caen Hill.

Posted by gje at 07:55 AM | Comments (0)

Dont bother to write a Perl program

I can - very easily - write a Perl program to process every line of an incoming data file - indeed, that's much of where Perl originated as the "Practical Extraction and Reporting Language"

Here's a short example that processes every line of a file and reports each line that includes the string PHP as the second field of our line (which in the example happens to be a person's top skill):

open (FH,"../../requests.xyz") or die;
while ($line = <FH>) {
 chop ($line);
 @F = split (/\s+/,$line) ;
 if ($F[1] eq "PHP") {
  print $line;
  print "\n";
 }
}

Quick and easy, for sure ... but not as short (nor as quick and easy) as it might be for someone who's written a lot of Perl - this one line does the same:

perl -pae '$F[1] eq "PHP" or $_ = ""' ../../requests.xyz

Perhaps this is so short as to be obscure? If you're working in an environment when you often have to filter out a file quickly, then it's an excellent approach. If you're doing a lot of shell scripting, then a few Perl one-liners like this can save you an awful lot of more complex looking awks and seds.

As Damien Conway (one of the Perl team) said when I heard him lecture: "We're giving you a lot of very powerful tools. Be careful how you use them".

Posted by gje at 05:53 AM | Comments (0)
Useful link: Perl training

October 09, 2008

Perl - map to process every member of a list (array)

Perl's map function (like array_walk in PHP) allows you to do something to every member of a list - thus it often saves you the need to write a loop into your Perl, saves the Perl runtime going back time and again to the interbal byte code generated by the compiler, and can be very efficient.

There aren't a large number of map examples in the training course notes that I use; in Perl there are many ways of doing anything and there are always alternatives but - as appropriate - I do add extra demonstrations in as I present the material. Here - four days into a five day course - are my examples of map so far this week:


@vals = map($_*5,@vals);

Take all the members of a list called @vals, multiply each of them by 5, are return them to a list of the same name (@vals), overwriting the original


$plist = join(", ",map (ucfirst lc, @peeps));

Take each element of the list in @peeps (probably people's names) and convert them all to lower case, then capitalise the first letter of their first name. Join the resulting names together with a space between each of them, and put the resulting single scalar string that results into a variable called $plist


map(printf("%20s %d\n",$_,$counter{$_}),@hio[0..9]);

Take the first ten elements of a list called @hio which in this example contained a sorted list of host computer names) and print out, formatted, the corresponding members of the hash called %counter - which contained elements keyed to those host names, with values which were the number of times that the particular host had accessed our server.

This last example is notable in that it makes no use of (throws away) the list returned by map - which will just be a list of "1" values indicating success - the important result is the effect of the 10 operations of printf

Posted by gje at 11:38 PM | Comments (0)
Useful link: Perl training

October 08, 2008

What a shock

You have probably seen the last pictures on this site ... taken with the digital camera I have been using for a couple of years. It was water resistant, contents-of-pocket resistant, and said to be shock resistant - but it turned out not be shock resistant enough for me - a clumsy oaf who managed to shut it into my Lisa's car door in Chippenham on Saturday evening. It now has a screen where I can see the left of the picture I'm taking but not the right, and where I have to guess at some of the menus. That I managed to do this half acceptably is shown by the pictures of Bathampton and Claverton Pump that have appeared here in the last few days.

"Get it fixed" is my first thought. Where other people have a mobile phone that becomes a very part of them, so was that camera to me. I have to watch how strongly I word the bond, as Lisa could end up thinking I have fonder words for the camera thaN I do for her (Lisa - if you're reading this - it is said tongue in cheek!). But the cost of fixing it would have been almost as much as (or perhaps more than) the new camera cost, and perhaps technology had moved on. Deep breath, I hadn't intended to get a new camera ... but it's new camera time!

So I'm back to learning a new camera now ... and you'll have to forgive me while I practise and post up a few trial and test photos ... here are some taken in the early days of this week.

The Town Hall at Melksham, with autumn flowers on the roundabout

This is the road works season in Melksham, and Bank Street is close once again!

Well House Manor early this morning, with bright sunlight on the front of the building.

Here's an interbal picture - our bedroom 3.

And here's my first picture with the new camera of delegates on a course.

I must admit that the new camera is a (10 Mpixel) development from the old one, so that although there are some things I need to get used to / learn into, it's much the same and I should be up and running again quite quickly.

Posted by gje at 04:12 PM | Comments (0)

Perl - Subs, Chop v Chomp, => v ,

During courses, I end up writing a lot of short demonstrations to show particular features of a language - this week, it's a Perl Programming Course so those examples are in Perl.

Some interesting Perl facts ...

a) The => operator can be used to replace the , ("the equals, greater than can be used to replace the comma")

b) chop and chomp have the same effect on a line of text just read in from STDIN (which usually means "read from the keyboard")

c) It's a good idea to take commonly repeated pieces of code and save them in a block - called a sub or subroutine in Perl - so that you don't have to keep repeating yourself AND so that you can present your user with a consistent interface

The programs I come up with are odd / quirky / memorable and if you look back at them later will leave the new reader scratching his or her head - but the key word is memorable. Here's the program that went some of the way to explaining the key perl facts above:

sub getui {
  print "$_[0] - ";
  chomp ($rv = <STDIN>);
  return $rv;
  }
 
print "How kids yagot? ";
chomp($nk = <STDIN>);
 
print "And how many goldfish? ";
chop($ng = <STDIN>);
 
$nz = getui("how many zebras?");
 
print "Actimel $nk pounds\n";
print "Cream Cheese ",$nk," kiddoes\n";
print "Milk $nk pounds\n";
print "Yoghurt "=>$ng=>" goldfish\n";
print "Bananas ",$nz," zebras\n";

Learning in this way is not only useful, but fun! If you're looking for the dates of the next public Perl course ... as I write (early October 2008) the next course starts on 27th October, and if you're reading this later on the archive and have missed that start date, you can find what's coming up here in our index of courses. I look forward to helping many more people (such as yourself, perhaps?) enjoy learning Perl!


Sample Output:

Dorothy:p1 grahamellis$ perl tootoo
How kids yagot? 3
And how many goldfish? 7
how many zebras? - 4
Actimel 3 pounds
Cream Cheese 3 kiddoes
Milk 3 pounds
Yoghurt 7 goldfish
Bananas 4 zebras

Posted by gje at 08:10 AM | Comments (0)
Useful link: Perl training

Question Mark - Colon operator (Perl and PHP)

The ? and : operator in Perl and PHP allows you to write a single statement that's both an if and an else without the need for all the clutter of keywords, extra variables, and so on if all you want to do is come up with two alternative words.

Here's an example in PHP - throwing a number on a die, and telling the user to proceed if the value thrown is a five or six, but to try again is it's a 1, 2, 3 or 4:

<?php
 
# Throw a die
 
$throw = rand(1,6);
 
print ("You threw a $throw which means you should ".
  (($throw > 4) ? "proceed" : "try again").
  " at the next turn\n");
 
?>

Here's how it works ("all our code is tested" as I wrote in an email to someone yesterday!)

Dorothy:p1 grahamellis$ php pz
You threw a 3 which means you should try again at the next turn
Dorothy:p1 grahamellis$ php pz
You threw a 6 which means you should proceed at the next turn
Dorothy:p1 grahamellis$

Here is the same functionallity using if and else:

<?php
 
# Throw a die
 
$throw = rand(1,6);
 
if ($throw > 4) {
  $action = "proceed";
} else {
  $action = "try again";
}
 
print ("You threw a $throw which means you should ".
  "$action at the next turn\n");
 
?>

In Perl (I'm running a Learning to Program in Perl course this week, which is where this article originated!), you have the same thing - and a wide variety of other convenient alternatives to if for conditionals and while for loops. I've posted up an example that uses until and also the ? : pairing at http://www.wellho.net/resources/ex.php4?item=p206/golf ... in this demonstration, you enter the number of individuals or teams you have signed up for a knock out competition, and the program tells you what your target should be if you want a perfect knockout with no need for any "byes" in the first round. Here it is running:

Dorothy:p1 grahamellis$ perl golf
How many people? 6
You really need 8
Dorothy:p1 grahamellis$ perl golf
How many people? 8
You're fine as you are with 8
Dorothy:p1 grahamellis$ perl golf
How many people? 11
You really need 16
Dorothy:p1 grahamellis$

You'll note - once again - the subtle use of ? : in the code to change the text "you'll really need ..." into "you're fine as you are with ..." - oh the power of Perl and its plethora of operators.

Posted by gje at 07:21 AM | Comments (0)
Useful links: Perl training, PHP training

October 07, 2008

Which is your best hotel room?

"Which Room would you recommend for a special weekend ..." Question on the phone from customer booking at Well House Manor. And Lisa's comment - "I feel awkward giving my personal opinion - it may differ from what the customer's would be." Well - give them the data and let the customer choose!

"We have a lot of customers who ask for the same room they were in last time when they book - and that's for every room in the hotel. Every room has its fans"

Room 1 is a quiet room at the back of the hotel, double, with a large circular-doored shower with a seat in it. [see bedroom 1]

Room 2 is larger that room 1 (mind you - room 1 is not small) again at the rear of the building, overlooking the main garden and the apple trees. Usually a double, we'll convert room 2 into a twin if required. [see bedroom 2]

Room 3 has a large sleigh bed and a double ended bath (no shower) in a light and airy bathroom. It overlooks the main lawn and is situated closed to the main stairs. [see bedroom 3]

Room 4 is the largest in the hotel - configured as either a double or twin room (please let us know when you book) and with a large walk in double shower. Again, this room overlooks the lawn. [see bedroom 4]

• and Room 5 is at the front of the hotel, with a King double bed, and both bath and shower. There's a fireplace in the room (regrettably not working) and the desk is situated in the bay window so that you can look out while you work. [see bedroom 5]

Which would I sleep in? Any of them ;-) ... and indeed I HAVE tried out some of them so that I'm fully aware of our product from a user's perspective, and we continue to encourage staff to stay and report back occasionally.

Posted by gje at 06:07 PM | Comments (0)

FSB - an update.

Last Tuesday, I got a phone call at lunch time asking me if I could attend - as a witness - a D&D (Dispute and Disciplinary) hearing of the FSB (Federation of Small Businesses) at Bath that afternoon. Unsurprisingly, I was giving a training course and couldn't oblige, but the D&D committee went out of their way to receive my input starting at 9 p.m. that evening, and lasting for over an hour.

Why me in particular? Well it wasn't me in particular - the hearing into allegations made by an employee of the FSB against the chair of our branch which had led to her being suspended from office for well over a year lasted for most of the week. I didn't comment earlier as it was "sub judice" (I think that's the term), but I am now happily able to report the verdict that cleared both our chair and her husband of the matters for which they were suspended for in late spring / early summer of last year.

The Committee's decision is a "narrow" one in that whilst it clears Marion and Malcolm, that's as far as the committee can go. As I understand it, it is beyond their remit to actually lift the suspension. Now you would think in the interests of common justice that such a lifting would happen immediately, with full recompense and re-instatement of Marion and Malcolm, wouldn't you. We'll have to wait and see on that one. With just the occasional exception, I've learned as I've watched this matter from the sidelines that the FSB is much more a member-led organisation in word than in deed.

If you would like to read back to my previous articles on this subject:

26th May 2008 - The old sayings are the best (FSB)

18th February 2008 - FSB, EGM, AGM.

19th January 2008 - Summer Ball at Bowood - Saturday 12th July 2008

20th December 2007 - FSB leaves its members feeling like mushrooms

13th September 2007 - FSB (Federation of Small Businesses) Western Region

27th June 2007 - Is this how to run a business for businesses?

And this is what the FSB should be about in my view - a business networking event on 20th April 2007 (yes, 18 months ago) where we had an opportunity to meet 19 other local businesses for our mutual benefit.

Another view of what the FSB should be doing. The Wilshire Business of the Year awards, 13th December 2006, in Swindon where we were finalists and teh FSB sponsored one of the sections

Here's hoping that the FSB can get its eye back on the ball soon ... that we can soon benefit again from our membership as we were doing in the Spring of last year, being piloted by a committee in North and West Wilts that we have elected from amongst all of our members, without exclusions, diversions or suspensions preventing it.

Posted by gje at 08:06 AM | Comments (0)

October 06, 2008

Claverton Pump

What's inside this little building that sits over a back water of the River Avon just a few miles up river from Bath?

A 25 foot wide water wheel, with each scoop on the wheel taking no less than half a ton of water [background], and a set of full functioning gears and flywheel - the whole being fully operational!

The fly wheel drives two huge beams, which in turn operate pumps that use to raise water up to the Kennet and Avon Canal that runs along the hillside above. Read more about it at the official site here.

The River Avon rises and falls quite dramatically at times of heavy rain, and indeed it was rising late yesterday when we dropped in by chance at the pumps.

Although shut(ting) down for the day, one of the team of volunteers briefly showed us around and I was able to take these pictures, including this one where he indicated where the two floods that have already had this summer rose to. Astonishingly, apart from moving some of the more delicate exhibits up above the water level, they can just let it flood - the engineering is so robust that it's not a major concern or panic - indeed, he also showed us the mud lines on the gears and flywheel which clearly indicated the angle they happened to have stopped at before the floods.

And a big THANK you to the gent - who's name I don't know - for letting us have that brief look around; it's little gestures like this, at the end of his day, which really "made" it for us.

Posted by gje at 07:24 AM | Comments (0)

October 05, 2008

Autumn

We're into Autumn, and on a blustery Sunday we went out to show Chris's mother in law, visiting from South Africa, some of the local scenes in Wiltshire, and Bath and North East Somerset (BaNES).

The hardier souls were out in the countryside - a handful of boats moving on the canal, fishermen, cyclists ... and of course the dog walkers, who will still be out walking their dogs long after the canals are beset with winter stoppages and the bicycles are in the back of the garages.

The Cafe at Avoncliff remains open from 10:30 a.m. until 6 p.m. until the clocks go back ... and of course the pubs continue to be open for extended hours as illustrated at Bathampton.

"Where's my master" asks one lonely, 4 legged soul left out in the cold!

Posted by gje at 11:41 PM | Comments (0)

Well House Consultants Ltd. Copyright 2008